第三模塊:面向對象&網絡編程基礎 第1章 面向對象

  • 個人失敗與夢想(一)
  • 個人失敗與夢想之爲什麼創辦路飛學城
  • 01-編程範式
  • 02-面向過程編程
  • 03-面向對象編程介紹
  • 04-定義類與實例化出對象
  • 05-如何使用類
  • 06-如何使用對象
  • 07-屬性查找與綁定方法
  • 08-Python中一切皆對象
  • 09-面向對象可拓展性總結
  • 10-小練習1
  • 11-小練習2
  • 12-繼承與重用性
  • 13-派生
  • 14-繼承的實現原理
  • 15-在子類中重用父類的方法或屬性
  • 16-組合
  • 17-抽象類與歸一化
  • 18-多態與多態性
  • 19-封裝之如何隱藏屬性
  • 20-封裝的意義
  • 21-封裝與可拓展性
  • 22-Property的使用
  • 23-綁定與非綁定方法介紹
  • 24-綁定方法與非綁定方法的使用
  • 25-反射
  • 26-內置方法介紹
  • 27-元類介紹
  • 28-自定義元類控制類的建立
  • 29-自定義元類與控制類的實例化行爲
  • 30-自定義元類與控制類的實例化行爲的應用
  • 31-面向對象的軟件開發與做業介紹
  • 32-什麼是異常處理
  • 33-try...except...詳細用法

個人失敗與夢想(一)

個人失敗與夢想之爲什麼創辦路飛學城

01-編程範式

一、什麼是面向對象編程?!編程範式

  • 數據結構:字符串、整型、列表、元組、字典、集合等,用來高效地存儲數據;
  • 算法:編寫程序的邏輯或者解決問題的流程;
  • 編程範式:武林中的各類流派;一大是面向過程,另外一大是面向對象;

02-面向過程編程

一、面向過程編程;

核心是過程二字,過程是指解決問題的步驟,即設計一條流水線,先作什麼,後作什麼,再作什麼,是一種機械式的思惟方式;html

  • 優勢:把複雜的問題流程化,進而簡單化;
  • 缺點:可拓展性比較差,應用場景:揚長避短,系統監控腳本,系統部署腳本,即需求變更不大的場景;
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 5:21
#需求,寫一個網站用戶註冊功能;使用面向過程的編程範式;
import json,re def interactive(): name = input('>>:').strip() passwd = input('>>:').strip() #拓展需求; email = input('>>:').strip() return { 'name':name, 'passwd':passwd, 'email':email, } def check(user_info): is_valid = True if len(user_info['name']) == 0: print('用戶名不能爲空。') is_valid = False if len(user_info['passwd']) < 6: print('密碼不能少於6位。') is_valid = False # 拓展需求; if not re.search(r'@.*?\.com$',user_info['email']): print('郵箱格式不合法。') is_valid = False return { 'is_valid':is_valid, 'user_info':user_info, } def register(check_info): if check_info['is_valid']: with open(file='db.json',mode='w',encoding='utf-8') as f: json.dump(check_info['user_info'],f) #定義主函數main() def main(): user_info = interactive() check_info = check(user_info) register(check_info) if __name__ == '__main__': main()

03-面向對象編程介紹

一、面向對象:特徵與技能的結合體即對象,好比孫悟空:外形特徵毛臉雷公嘴,手持金箍棒具有七十二變化,火眼金睛等技能(上帝的思惟方式,在上帝眼裏,一切皆對象!);

  • 優勢:是面向過程的缺點,便可拓展性強;
  • 缺點:是面向過程的優勢,編程複雜性高;
  • 應用場景:用戶需求常常變化,好比和互聯網應用、遊戲、企業內部應用,好比OA、ERP;

04-定義類與實例化出對象

一、類的定義:即一系列對象類似的特徵與技能的結合體(一系列類似的對象成爲類),好比人類,豬類,狗類,電腦類,筆類,花類;

強調:站在不一樣的角度,獲得的分類是不同的,好比站在實體的角度,人和鉛筆、計算機是一類;站在生物的角度,以上就不是相同的一類;java

二、先有類仍是先有對象?!

  • 在現實世界中:先有對象,對象自我學習後總結出類的概念,好比人類,豬類、狗類、生物類;
  • 在程序中:必定得先定義類,後經過調用類來產生對象;類至關於模版!好比公司招聘人的時候,會定義一個崗位招聘標準,這個標準就至關於類!那麼研發部的全體成員成爲技術類羣體;

三、站在路飛學城的角度,你們都是學生;

  • 在現實世界中:對象一、二、3的特徵與技能;
  • 總結現實中路飛學城的學生類:一、類似的特徵;二、類似的技能;
  • 在程序中,必定是先定義類,後產生對象,注意該順序;

 四、定義類的方式(方法);

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 5:47
""
"""
一、將對象進行分類,好比PC、筆記本;
"""
#使用clasee關鍵字,先定義類;
class LuffyStudent:#類名首字母大寫;
    school = 'luffycity'
    def learn(self):#技能就是功能,經過函數方式進行定義!
        print('is learning.')
    def eat(self):
        print('is eating.')
    def sleep(self):
        print('is sleeping.')
#後產生對象;
student1 = LuffyStudent()#類產生對象的這個過程也稱爲實例化的過程;類名加()有別於函數名加括號;
student2 = LuffyStudent()
student3 = LuffyStudent()

print(student1)#<__main__.LuffyStudent object at 0x000001E494370B00>#對象在類中的內存地址;
print(student2)#<__main__.LuffyStudent object at 0x000001E494370B38>
print(student3)#<__main__.LuffyStudent object at 0x000001E494370AC8>

05-如何使用類

一、類的增刪改查;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 6:05
#先定義類;
class LuffyStudent:#類名首字母大寫;
    school = 'luffycity'#特徵,以變量的形式定義;
    def learn(self):#技能1,以函數的形式定義;
        print('is learning.')
    def eat(self):#技能2,以函數的形式定義;
        print('is eating.')
    def sleep(self):#技能3,以函數的形式定義;
        print('is sleeping.')
#查看類的名稱空間;
print(LuffyStudent.__dict__)#{'__module__': '__main__', 'school': 'luffycity', 'learn': <function LuffyStudent.learn at 0x000001A59EE71AE8>, 'eat': <function LuffyStudent.eat at 0x000001A59EE71EA0>, 'sleep': <function LuffyStudent.sleep at 0x000001A59EE71B70>, '__dict__': <attribute '__dict__' of 'LuffyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'LuffyStudent' objects>, '__doc__': None}
print(LuffyStudent.__dict__['school'])#luffycity
print(LuffyStudent.__dict__['learn'])#<function LuffyStudent.learn at 0x0000021C5B221AE8>
"""
類內部定義的變量稱之爲:數據屬性;
類內部定義的函數稱之爲:函數屬性;
"""
#import time
#time.sleep(1)
#查看;
print(LuffyStudent.school)#luffycity
print(LuffyStudent.learn)#<function LuffyStudent.learn at 0x000002A0CD0B1AE8>
#增長;
LuffyStudent.country = 'China'#定義新的數據屬性(即公共的特性,變量名),進行賦值;
#print(LuffyStudent.__dict__)
#使用專門的語法進行;
print(LuffyStudent.country)#China
#刪除;
del LuffyStudent.country
print(LuffyStudent.__dict__)#發現country已經被刪除;
#print(LuffyStudent.country)#AttributeError: type object 'LuffyStudent' has no attribute 'country'

#改;
LuffyStudent.school = 'Luffycity'#即從新賦值;
print(LuffyStudent.school)#Luffycity

"""
小結:
一、函數名加(),執行函數;
二、類名加(),實例化獲得一個對象;
三、類的用途:對類屬性的操做——增刪改查;實例化產生出對象;
四、類與函數的區別,類在定義階段,就已經被執行;
五、類的兩大操做,第一,類的增刪改查;第二,類的實例化產生對象;
"""

06-如何使用對象

一、對象的增刪改查操做;

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 6:41
#__init__方法,用來爲對象定製對象本身獨有的特徵;好比崔曉昭、崔曉珊、崔曉思、崔曉磊都屬於崔家類,但都有各自的屬性;好比職業、年齡、身高、體重、價值觀等等;
#先定義類;
class LuffyStudent:#類名首字母大寫;
    school = 'luffycity'
    #student1,'王二丫','女',18
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
        #student1.Name='王二丫'
        #student2.Sex='女'
        #student3.Age=18
    def learn(self):
        print('is learning.')
    def eat(self):
        print('is eating.')
    def sleep(self):
        print('is sleeping.')
#後產生對象;
#student1 = LuffyStudent()#TypeError: __init__() missing 3 required positional arguments: 'name', 'sex', and 'age'
#進行類的實例化的時候,Python會自動調用__init__對象;
student1 = LuffyStudent('王二丫','',18)
#加上__init__方法後,實例化的步驟;
"""
一、先產生一個空對象student1;
二、LuffyStudent.__init__(student1,'王二丫','女',18)
"""
#查詢;
print(student1.__dict__)#{'Name': '王二丫', 'Sex': '女', 'Age': 18}
print(student1.name)#王二丫
print(student1.age)#18
print(student1.sex)#
#改-即對對象的從新賦值操做;
student1.Name = '李靜瓶'
print(student1.__dict__)#{'Name': '李靜瓶', 'Sex': '女', 'Age': 18}
print(student1.Name)#李靜瓶
#刪除
del student1.Name#使用del 方法;
print(student1.__dict__)
#增長
student1.Course = 'Python全棧開發'#{'name': '王二丫', 'sex': '女', 'age': 18, 'Course': 'Python全棧開發'}
print(student1.__dict__)

#如何產生對象2:student2操做
student2 = LuffyStudent('李三炮','',38)
print(student2.__dict__)#{'Name': '李三炮', 'Sex': '男', 'Age': 38}
print(student2.name)#李三炮
print(student2.age)#38
print(student2.sex)#
#問題1:在對象中,可否訪問到類裏面的公共屬性呢?!

 

07-屬性查找與綁定方法

一、綁定方法與屬性查找;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 7:04
#先定義類;
class LuffyStudent:#類名首字母大寫;
    school = 'luffycity'
    #student1,'王二丫','女',18
    def __init__(self,name,sex,age):
        self.Name = name
        self.Sex = sex
        self.Age = age
        #student1.Name='王二丫'
        #student2.Sex='女'
        #student3.Age=18
    def learn(self):
        #print('is learning.')
        print('%s is learning'%self.Name)
    def eat(self):
        print('is eating.')
    def sleep(self):
        print('is sleeping.')
#後產生對象;
#student1 = LuffyStudent()#TypeError: __init__() missing 3 required positional arguments: 'name', 'sex', and 'age'
#Python會自動調用__init對象;
student1 = LuffyStudent('王二丫','',18)
student2 = LuffyStudent('李三炮','',38)
student3 = LuffyStudent('張鐵蛋','',48)
print(student1.__dict__)
print(student2.__dict__)
print(student3.__dict__)
""
{'Name': '王二丫', 'Sex': '', 'Age': 18}
{'Name': '李三炮', 'Sex': '', 'Age': 38}
{'Name': '張鐵蛋', 'Sex': '', 'Age': 48}
""
#對象:特徵與技能的結合體,好比孫悟空這個角色;
#類:類是一系列對象類似的特徵與類似的技能的結合體;

#類中的數據屬性:是全部的對象公共的即共有的;
print(LuffyStudent.school)
print(student1.school,id(student1.school))
print(student2.school,id(student2.school))
print(student3.school,id(student3.school))
"""
luffycity
luffycity 2904853177648
luffycity 2904853177648
luffycity 2904853177648
"""
#類中的函數屬性:是綁定給對象使用的,綁定到不一樣的對象是不一樣的綁定方法;
#對象調用綁定方法時候,會把對象自己,當作第一個函數傳入,傳給self;
print(LuffyStudent.learn)
print(student1.learn)
print(student2.learn)
print(student3.learn)
"""
<function LuffyStudent.learn at 0x00000234A0FC1B70>#函數;
<bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x00000234A0FC5C88>>#bound method綁定方法;
<bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x00000234A0FC5CC0>>
<bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x00000234A0FC5CF8>>
"""
#LuffyStudent.learn()#TypeError: learn() missing 1 required positional argument: 'self'
LuffyStudent.learn(student1)#王二丫 is learning
student1.learn()#王二丫 is learning
"""
小結:
一、類中定義的函數是給對象使用的,綁定給對象使用,不一樣的對象具有相同的技能,但內存地址不一致;
"""
student1.x = 'from student1'#給對象增長一個屬性;
LuffyStudent.x = 'from LuffyCity class '
print(student1.__dict__)#{'Name': '王二丫', 'Sex': '女', 'Age': 18, 'x': 'from student1'}
print(student1.x)#from student1

08-Python中一切皆對象

一、一切皆對象的解釋說明;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 7:30
""
"""
小結:
一、站的角度不一樣,定義出的類是大相徑庭的;
二、現實生活中的類不徹底等於程序中的類,好比現實中的公司類,在程序中有時須要拆分紅部門類、業務類等;
三、有時候爲了編程需求,程序中也有可能會定義現實中不存在的類,好比策略類,現實中並不存在,可是在程序中倒是一個很常見的類;
補充:
一、Python當中一切皆對象,Python3.x中統一了類與數據類型的概念;
"""
#先定義類;
class LuffyStudent:#類名首字母大寫;
    school = 'luffycity'
    #student1,'王二丫','女',18
    def __init__(self,name,sex,age):
        self.Name = name
        self.Sex = sex
        self.Age = age
        #student1.Name='王二丫'
        #student2.Sex='女'
        #student3.Age=18
    def learn(self):
        #print('is learning.')
        print('%s is learning'%self.Name)
    def eat(self):
        print('is eating.')
    def sleep(self):
        print('is sleeping.')
print(LuffyStudent)
print(list)
"""
<class '__main__.LuffyStudent'>
<class 'list'>
"""
l1 = [1,2,3]#等價於,l1 = list([1,2,3])
l2 =[]#等價於,l2 = list([])
#列表的內置方法;
l1.append(4)
print(l1)#[1, 2, 3, 4]
print(l2)#[]
list.append(l1,4)#雖然能夠實現功能,可是沒人這麼用,咱們都是使用對象的綁定方法;好比l1.append()
print(l1)#[1, 2, 3, 4, 4],效果等價於l1.append(4)
#總結:針對於對象,咱們使用的都是對象的綁定方法來操做;能夠簡單理解,類就是咱們自定義的list、tuple、set等數據類型;

09-面向對象可拓展性總結

 一、面向對象拓展性總結;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 7:40
""
class Chinese:
    country = 'China'
    def __init__(self,name,sex,age):
        self.Name = name
        self.Sex = sex
        self.Age = age
        #student1.Name='王二丫'
        #student2.Sex='女'
        #student3.Age=18
    def learn(self):
        #print('is learning.')
        print('%s is learning'%self.Name)
    def eat(self):
        print('%s is eating.'%self.Name)
p1 = Chinese('egon',18,'male')
p2 = Chinese('alex',38,'female')
p3 = Chinese('wqp',48,'female')
print(p1.country)#china
print(p2.country)#china
print(p3.country)#china

p1.eat()
p2.eat()
p3.eat()
"""
egon is eating.
alex is eating.
wqp is eating.
"""

 

從代碼級別看面向對象
1、在沒有學習類這個概念時,數據與功能是分離的;

def exc1(host,port,db,charset):
    conn=connect(host,port,db,charset)
    conn.execute(sql)
    return xxx


def exc2(host,port,db,charset,proc_name)#proc_name是MySQL中的存儲過程;
    conn=connect(host,port,db,charset)
    conn.call_proc(sql)
    return xxx

#每次調用都須要重複傳入一堆參數;
exc1('127.0.0.1',3306,'db1','utf8','select * from tb1;')
exc2('127.0.0.1',3306,'db1','utf8','存儲過程的名字')
2、咱們能想到的解決方法是,把這些變量都定義成全局變量;

HOST=‘127.0.0.1’#大寫字母表明常量;
PORT=3306
DB=‘db1’
CHARSET=‘utf8’

def exc1(host,port,db,charset):
    conn=connect(host,port,db,charset)
    conn.execute(sql)
    return xxx


def exc2(host,port,db,charset,proc_name)
    conn=connect(host,port,db,charset)
    conn.call_proc(sql)
    return xxx

exc1(HOST,PORT,DB,CHARSET,'select * from tb1;')
exc2(HOST,PORT,DB,CHARSET,'存儲過程的名字')
3、可是2的解決方法也是有問題的,按照2的思路,咱們將會定義一大堆全局變量,這些全局變量並無作任何區分,即可以被全部功能使用,然而事實上只有HOST,PORT,DB,CHARSET是給exc1和exc2這兩個功能用的。言外之意:咱們必須找出一種可以將數據與操做數據的方法組合到一塊兒的解決方法,這就是咱們說的類了

class MySQLHandler:#注意此處沒有();
    def __init__(self,host,port,db,charset='utf8'):
        self.host=host
        self.port=port
        self.db=db
        self.charset=charset
        self.conn=connect(self.host,self.port,self.db,self.charset)
    def exc1(self,sql):
        return self.conn.execute(sql)

    def exc2(self,sql):
        return self.conn.call_proc(sql)


obj=MySQLHandler('127.0.0.1',3306,'db1')
obj.exc1('select * from tb1;')
obj.exc2('存儲過程的名字')
總結使用類能夠:

一、將數據與專門操做該數據的功能整合到一塊兒;
二、可擴展性高;
三、定義類併產生三個對象;

class Chinese:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

p1=Chinese('egon',18,'male')
p2=Chinese('alex',38,'female')
p3=Chinese('wpq',48,'female')
若是咱們新增一個類屬性,將會馬上反映給全部對象,而對象卻無需修改;

class Chinese:
    country='China'
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def tell_info(self):
        info='''
        國籍:%s
        姓名:%s
        年齡:%s
        性別:%s
        ''' %(self.country,self.name,self.age,self.sex)
        print(info)
p1
=Chinese('egon',18,'male') p2=Chinese('alex',38,'female') p3=Chinese('wpq',48,'female') print(p1.country) p1.tell_info()

 

10-小練習1

一、練習No.01;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 21:03
""
"""
一、練習1:編寫一個學生類,產生一堆學生對象;
要求:
有一個計算器(屬性),統計總共實例化了多少個對象。count方法統計;
"""
class Student:#定義一個Student類名,注意首字母大寫;
    school = 'luffycity'
    count = 0#在類中定義計數器變量count
    def __init__(self,name,age,sex):#約定俗稱,你們都寫self,能夠寫成其餘的,可是沒人這麼幹!
        self.name = name
        self.age = age
        self.sex = sex
        #self.Come = come
        Student.count +=1#經過類名的count方法統計調用次數,每調用一次,自增1;
        #self.count = self.count+1
    def learn(self):
        print('%s is learning'%self.name)
#實例化;
stu1=Student('alex','male',38)
stu2=Student('jinxing','female',78)
stu3=Student('egon','male',18)

print(Student.count)
print(stu1.count)
print(stu2.count)
print(stu3.count)

print(stu1.__dict__)
print(stu2.__dict__)
print(stu3.__dict__)
"""
3
3
3
3
{'Name': 'alex', 'Age': 'male', 'Sex': 38}
{'Name': 'jinxing', 'Age': 'female', 'Sex': 78}
{'Name': 'egon', 'Age': 'male', 'Sex': 18}
"""

11-小練習2

一、練習No.02;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 21:20
""
"""
一、練習2:模仿LOL定義兩個英雄類;
要求:
一、英雄須要有暱稱、攻擊力、生命值等屬性;
二、實例化出兩個英雄對象;
三、英雄之間能夠互毆,被毆打的一方開始掉血,血量小於0則斷定爲死亡;
"""
#定義LOL中英雄的名稱;
class Garen:
    camp = 'Demacia'#德瑪西亞;
    def __init__(self,nickname,life_value,aggresivity):
        self.nickname = nickname
        self.life_value = life_value
        self.aggresivity = aggresivity
    def attact(self,enemy):
        enemy.life_value -= self.aggresivity

class Riven:
    camp = 'Noxus'#xxxx;
    def __init__(self,nickname,life_value,aggresivity):
        self.nickname = nickname
        self.life_value = life_value
        self.aggresivity = aggresivity
    def attact(self,enemy):
        enemy.life_value -= self.aggresivity
g1=Garen('草叢倫',100,30)
r1 = Riven('可愛的芮雯雯',80,50)
#打印初始生命值;
print(r1.life_value)#80
g1.attact(r1)
#打印被攻擊一次後的生命值;
print(r1.life_value)#50

12-繼承與重用性

一、初識繼承;

繼承指的是類與類之間的關係,是一種什麼「是」什麼的關係,繼承的功能之一就是用來解決代碼重用問題;

繼承是一種建立新類的方式,在python中,新建的類能夠繼承一個或多個父類,父類又能夠成爲基類或超類,新建的類稱爲派生類或子類;

  • python中類的繼承分爲:單繼承和多繼承;
class ParentClass1: #定義父類;
    pass
class ParentClass2: #定義父類;
    pass
class SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClass;
    pass
class SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號分隔開多個繼承的類;
    pass
  • 查看繼承
>>> SubClass1.__bases__ #__base__只查看從左到右繼承的第一個子類,__bases__則是查看全部繼承的父類;
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
  • 經典類與新式類
1.只有在python2中才分新式類和經典類,python3中統一都是新式類;
2.在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經典類;
3.在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類;
4.在python3中,不管是否繼承object,都默認繼承object,即python3中全部類均爲新式類;

二、如何來理解抽象,抽出對象或類類似的地方,叫作抽象;

三、抽象分紅兩個層次:

  • 一、將奧巴馬和梅西這倆對象比較像的部分抽取成類;
  • 二、將人、豬、狗這三個類比較像的部分抽取成父類;
  • 三、抽象最主要的做用是劃分類別(能夠隔離關注點,下降複雜度);

繼承:是基於抽象的結果,經過編程語言去實現它,確定是先經歷抽象這個過程,才能經過繼承的方式去表達出抽象的結構。

# #!/usr/bin/env python
# # -*- coding:utf-8 -*-
# # __Author__:Administrator
# # Version:python3.6.5
# # Date:2018/6/12 0012 21:38
# #定義一個父類1;
# class ParentClass1:
#     pass
# #定義一個父類2;
# class ParentClass2:
#     pass
# #定義一個子類1;
# class SubClass1(ParentClass1):
#     pass
# #定義一個子類2;同時繼承兩個父類;
# class SubClass2(ParentClass1,ParentClass2):
#     pass
#__bases__方法,查看繼承了哪一個父類;
# print(SubClass1.__bases__)#(<class '__main__.ParentClass1'>,) # print(SubClass2.__bases__)#(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>) #解決代碼之間冗餘問題; class Hero:#定義一個英雄類; x = 3 def __init__(self,nickname,life_value,aggresivity):#屬性; self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attact(self,enemy):#攻擊技能; enemy.life_value -= self.aggresivity class Garen(Hero): #x = 2 pass#德瑪西亞; class Riven(Hero): pass g1=Garen('剛們',29,30) print(g1.nickname,g1.life_value,g1.aggresivity)#剛們 29 30; #繼承,實現代碼的重用性! #那麼問題來了,屬性的查找順序是怎樣的? #g1.x =1 print(g1.x) #屬性查找的小練習; class Foo: def f1(self): print('from Foo.f1') def f2(self): print('from Foo.f2') self.f1()#b.f1(),注意查找順序,從下往上查找; class Bar(Foo): def f1(self): print('from Bar.f1') b = Bar() print(b.__dict__) b.f2() b.f1()#注意查找順序; """
from Foo.f2
from Bar.f1 from Bar.f1 """

13-派生

一、派生的概念引入;

  • 在繼承的基礎上,衍生出新的技能;
  • 當子類派生出新的技能時候,優先使用自身;
  • 固然子類也能夠添加本身新的屬性或者在本身這裏從新定義這些屬性(不會影響到父類),須要注意的是,一旦從新定義了本身的屬性且與父類重名,那麼調用新增的屬性時,就以本身爲準了。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 22:17
#派生的概念引入;
class Hero:#定義一個英雄類;
    def __init__(self,nickname,life_value,aggresivity):#屬性;
        self.nickname = nickname
        self.life_value = life_value
        self.aggresivity = aggresivity
    def attact(self,enemy):#攻擊技能;
        enemy.life_value -= self.aggresivity
class Garen(Hero):
    camp ='Demacia'#德瑪西亞;
class Riven(Hero):
    camp = 'Noxus'
g = Garen('草叢倫',100,30)
r = Riven('銳雯雯',80,50)
print(g.camp)#Demacia
g.attact(r)
print(r.life_value)#50

14-繼承的實現原理

一、繼承的實現原理;

python究竟是如何實現繼承的,對於咱們定義的每個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的全部基類的線性順序列表,例如;python

>>> F.mro() #等同於F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] 

爲了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類爲止。而這個MRO列表的構造是經過一個C3線性化算法來實現的。咱們不去深究這個算法的數學原理,它實際上就是合併全部父類的MRO列表並遵循以下三條準則:linux

  1. 子類會先於父類被檢查;
  2. 多個父類會根據它們在列表中的順序被檢查;
  3. 若是對下一個類存在兩個合法的選擇,選擇第一個父類;

在Java和C#中子類只能繼承一個父類,而Python中子類能夠同時繼承多個父類,若是繼承了多個父類,那麼屬性的查找方式有兩種,分別是:深度優先和廣度優先;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/12 0012 22:27
""
"""
Python分爲兩種類;
一、新式類; 二、經典類; 在Python2中,沒有繼承object的類以及它的子類都稱之爲經典類;
在Python2中,繼承了object的類以及它的子類都稱之爲新式類;
""" # class Foo: # pass # class Bar(Foo): # pass # #在Python3中統一爲新式類,一個類沒有繼承object類,默認就繼承object; # class Foo(): # pass # print(Foo.__bases__) #驗證多繼承狀況下的屬性查找順序; class A(object):#Python2中經典類去掉object # def test(self): # print('from A') pass#AttributeError: 'F' object has no attribute 'test' class B(A): # def test(self): # print('from B') pass class C(A): # def test(self): # print('from C') pass class D(B): # def test(self): # print('from D') pass class E(C): # def test(self): # print('from E') pass class F(D,E): # def test(self): # print('from F') pass #FDBECA # f=F() # f.test() print(F.mro())#[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
print(F.__mro__) #只有新式纔有這個屬性能夠查看線性列表,經典類沒有這個屬性; #新式類繼承順序:F->D->B->E->C->A; #經典類繼承順序:F->D->B->A->E->C; #python3中統一都是新式類; #pyhon2中才分新式類與經典類;
 

15-在子類中重用父類的方法或屬性

一、子類中重用父類的方法或屬性;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/13 0013 23:22
# class Hero:#定義一個英雄類;
#     def __init__(self,nickname,life_value,aggresivity):#屬性;
#         self.nickname = nickname
#         self.life_value = life_value
#         self.aggresivity = aggresivity
#     def attact(self,enemy):#攻擊技能;
#         enemy.life_value -= self.aggresivity
# class Garen(Hero):
#     camp ='Demacia'#德瑪西亞;
#     def attack(self,enemy):
#         Hero.attact(self.enemy)#在子類當中,重用父類的方法,即指名道姓的重用父類的方法;
#         print('from Garen Class')
#
# class Riven(Hero):
#     camp = 'Noxus'
#
# g = Garen('草叢倫',100,30)
# r = Riven('銳雯雯',80,50)
#
# print(r.life_value)#80
# g.attact(r)#進行攻擊;
# print(r.life_value)#50;

# class Hero:#定義一個英雄類;
#     def __init__(self,nickname,life_value,aggresivity):#屬性;
#         self.nickname = nickname
#         self.life_value = life_value
#         self.aggresivity = aggresivity
#     def attact(self,enemy):#攻擊技能;
#         enemy.life_value -= self.aggresivity
# class Garen(Hero):
#     camp ='Demacia'#德瑪西亞;
#     def __init__(self,nickname,life_value,aggresivity,weapon):
#         #self.nickname = nickname
#         #self.life_value = life_value
#         #self.aggresivity = aggresivity
#         self.weapon = weapon
#         Hero.__init__(self,nickname,life_value,aggresivity)#實現了代碼節省的方法;
#     def attack(self,enemy):
#         Hero.attact(self.enemy)#指名道姓;
#         print('from Garen Class')
#
#
#
# #g = Garen('草叢倫',100,30)#TypeError: __init__() missing 1 required positional argument: 'weapon'
# g = Garen('草叢倫',100,30,'金箍棒')
# print(g.__dict__)#{'nickname': '草叢倫', 'life_value': 100, 'aggresivity': 30, 'weapon': '金箍棒'}
""
"""
一、在子類派生出的新的方法中重用父類的方法,有兩種實現方式;
方式一:指名道姓(不依賴繼承);
方式二:super()方法(依賴繼承);
"""
#方式二:super()方法;
# class Hero:#定義一個英雄類;
#     def __init__(self,nickname,life_value,aggresivity):#屬性;
#         self.nickname = nickname
#         self.life_value = life_value
#         self.aggresivity = aggresivity
#     def attack(self,enemy):#攻擊技能;
#         enemy.life_value -= self.aggresivity
#
# class Garen(Hero):
#     camp = 'Demacia'#德瑪西亞;
#     def attack(self,enemy):
#         super(Garen,self).attack(enemy)#依賴繼承的方式,進行重用父類的方法;
#         print('from Garen Class')
#
# class Riven(Hero):
#     camp = 'Noxus'
#
# g = Garen('草叢倫',100,30)
# r = Riven('銳雯雯',80,50)
# g.attack(r)
# print(r.life_value)



# class Hero:#定義一個英雄類;
#     def __init__(self,nickname,life_value,aggresivity):#屬性;
#         self.nickname = nickname
#         self.life_value = life_value
#         self.aggresivity = aggresivity
#     def attact(self,enemy):#攻擊技能;
#         enemy.life_value -= self.aggresivity
# class Garen(Hero):
#     camp ='Demacia'#德瑪西亞;
#     def attack(self,enemy):
#         Hero.attact(self.enemy)#指名道姓;
#         print('from Garen Class')
#
# class Riven(Hero):
#     camp = 'Noxus'
#
# g = Garen('草叢倫',100,30)
# r = Riven('銳雯雯',80,50)
#
# print(r.life_value)#80
# g.attact(r)
# print(r.life_value)#50

# class Hero:#定義一個英雄類;
#     def __init__(self,nickname,life_value,aggresivity):#屬性;
#         self.nickname = nickname
#         self.life_value = life_value
#         self.aggresivity = aggresivity
#     def attack(self,enemy):#攻擊技能;
#         enemy.life_value -= self.aggresivity
# class Garen(Hero):
#     camp ='Demacia'#德瑪西亞;
#     def __init__(self,nickname,life_value,aggresivity,weapon):
#         #self.nickname = nickname
#         #self.life_value = life_value
#         #self.aggresivity = aggresivity
#         #self.weapon = weapon
#         #Hero.__init__(self,nickname,life_value,aggresivity)#
#         #super(Garen,self).__init__(nickname,life_value,aggresivity)#與下方實現效果等價;
#         super().__init__(nickname,life_value,aggresivity)#Python3中super方法的簡寫方式;
#         self.weapon = weapon
#     def attack(self,enemy):
#         Hero.attack(self,enemy)#指名道姓;
#         print('from Garen Class')
#
# #g = Garen('草叢倫',100,30)#TypeError: __init__() missing 1 required positional argument: 'weapon'
# g = Garen('草叢倫',100,30,'金箍棒')
# print(g.__dict__)#{'nickname': '草叢倫', 'life_value': 100, 'aggresivity': 30, 'weapon': '金箍棒'}

#證實以下: class A: def f1(self): print('from A') class B: def f2(self): print('from B') class C(A,B): pass print(C.mro())#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]#c的mro排列順序查找;

16-組合

一、什麼是組合;

  • 軟件重用的重要方式除了繼承以外還有另一種方式,即:組合
  • 組合指的是,在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合;

二、組合與繼承都是有效地利用已有類的資源的重要方式,可是兩者的概念和使用場景皆不一樣;

1)繼承的方式程序員

經過繼承創建了派生類與基類之間的關係,它是一種'是'的關係,好比白馬是馬,人是動物;算法

當類之間有不少相同的功能,提取這些共同的功能作成基類,用繼承比較好,好比老師是人,學生是人;sql

2)組合的方式編程

用組合的方式創建了類與組合的類之間的關係,它是一種‘有’的關係,好比教授有生日,教授教python和linux課程,教授有學生s一、s二、s3...json

示例:繼承與組合網絡

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/16 0016 21:05
# class Teacher:#定義講師類;
#     school = 'luffycity'
#     def __init__(self,name,age,sex,level,salary):
#         self.name = name
#         self.age = age
#         self.sex = sex
#         self.level = level
#         self.salary = salary
#     def teach(self):
#         print('%s is teaching Python course'%self.name)
#
# #定義學生類;
# class Student:#定義學生類;
#     school = 'luffycity'
#     def __init__(self,name,age,sex,class_time):
#         self.name = name
#         self.age = age
#         self.sex = sex
#         self.class_time = class_time
#     def learn(self):
#         print('%s is learning Python course'%self.name)
""
"""
以上出現了代碼重用的現象,so抽取學生和講師公共的部分,定義People類;
"""
#定義People類;
class People:
    school = 'luffycity'
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

class Teacher(People):#經過繼承方式,定義講師類;
    def __init__(self,name,age,sex,level,salary):
        super().__init__(name,age,sex)
        self.level = level
        self.salary = salary
    def teach(self):
        print('%s is teaching Python course'%self.name)

#定義學生類;
class Student(People):#經過繼承方式,定義學生類;
    school = 'luffycity'
    def __init__(self,name,age,sex,class_time):
        super().__init__(name, age, sex)
        self.class_time = class_time
    def learn(self):
        print('%s is learning Python course'%self.name)
#定義課程類;
class Course:
    def __init__(self,course_name,course_price,course_period):
        self.course_name = course_name
        self.course_price = course_price
        self.course_period = course_period
    #再定義課程信息類;
    def Tell_info(self):
        print('課程名《%s》 課程價格《%s》 課程週期《%s》'%(self.course_name,self.course_price,self.course_period))

class Date:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
    def tell_info(self):
        print('%s-%s-%s'%(self.year,self.month,self.day))
#經過類實例化,產生對象;
teacher1 = Teacher('alex',18,'male',10,3000)
teacher2 = Teacher('egon',28,'male',10,3000)
python = Course('Python',3000,'3months')
linux = Course('Linux',4000,'4months')

teacher1.course = python
teacher2.course = python

print(python)
print(teacher1.course)
print(teacher2.course)
"""
<__main__.Course object at 0x000001CD7CF35F98>
<__main__.Course object at 0x000001CD7CF35F98>
<__main__.Course object at 0x000001CD7CF35F98>
"""
#teacher1 = Teacher('alex',18,'male',10,3000,'Python',3000,'3months')
#teacher2 = Teacher('egon',28,'male',10,3000,'Python',3000,'3months')

#如何查看老師課程信息;
print(python.course_name)
print(python.course_period)
print(python.course_price)
#等價於以下所示;
print(teacher1.course.course_name)#Python
print(teacher1.course.course_period)#3months
print(teacher1.course.course_price)#3000

#查看老師的課程信息的方法;
teacher1.course.Tell_info()#這種方式就叫作組合;課程名《Python》 課程價格《3000》 課程週期《3months》
student1 = Student('張三',28,'female','08:30:00')
student1.course1 = python
student1.course2 = linux
#查看學生的課程信息的方法;
student1.course1.Tell_info()#課程名《Python》 課程價格《3000》 課程週期《3months》
student1.course2.Tell_info()#課程名《Linux》 課程價格《4000》 課程週期《4months》

student3 = Student('崔曉昭',28,'male','09:00:00')
d = Date(1993,9,11)
student3.birth = d
student3.birth.tell_info()#1993-9-11
""
"""
小結:
一、#什麼有什麼,便可使用組合的方式進行代碼重用;
二、#什麼是什麼,即便用繼承的方式進行代碼重用;
"""

17-抽象類與歸一化

一、抽象類的初識;

1)接口與歸一化設計;

二、什麼是接口?!

hi boy,給我開個查詢接口。。。此時的接口指的是:本身提供給使用者來調用本身功能的方式\方法、入口,java中的interface使用以下:

=================第一部分:Java 語言中的接口很好的展示了接口的含義: IAnimal.java
/*
* Java的Interface接口的特徵:
* 1)是一組功能的集合,而不是一個功能;
* 2)接口的功能用於交互,全部的功能都是public,即別的對象可操做;
* 3)接口只定義函數,但不涉及函數實現;
* 4)這些功能是相關的,都是動物相關的功能,但光合做用就不適宜放到IAnimal裏面了*/

package com.oo.demo;
public interface IAnimal {
    public void eat();
    public void run(); 
    public void sleep(); 
    public void speak();
}

=================第二部分:Pig.java:豬」的類設計,實現了IAnnimal接口 
package com.oo.demo;
public class Pig implements IAnimal{ //以下每一個函數都須要詳細實現
    public void eat(){
        System.out.println("Pig like to eat grass");
    }

    public void run(){
        System.out.println("Pig run: front legs, back legs");
    }

    public void sleep(){
        System.out.println("Pig sleep 16 hours every day");
    }

    public void speak(){
        System.out.println("Pig can not speak"); }
}

=================第三部分:Person2.java
/*
*實現了IAnimal的「人」,有幾點說明一下: 
* 1)一樣都實現了IAnimal的接口,但「人」和「豬」的實現不同,爲了不太多代碼致使影響閱讀,這裏的代碼簡化成一行,但輸出的內容不同,實際項目中同一接口的同一功能點,不一樣的類實現徹底不同;
* 2)這裏一樣是「人」這個類,但和前面介紹類時給的類「Person」徹底不同,這是由於一樣的邏輯概念,在不一樣的應用場景下,具有的屬性和功能是徹底不同的 */

package com.oo.demo;
public class Person2 implements IAnimal { 
    public void eat(){
        System.out.println("Person like to eat meat");
    }

    public void run(){
        System.out.println("Person run: left leg, right leg");
    }

    public void sleep(){
        System.out.println("Person sleep 8 hours every dat"); 
    }

    public void speak(){
        System.out.println("Hellow world, I am a person");
    } 
}

=================第四部分:Tester03.java
package com.oo.demo;

public class Tester03 {
    public static void main(String[] args) {
        System.out.println("===This is a person==="); 
        IAnimal person = new Person2();
        person.eat();
        person.run();
        person.sleep();
        person.speak();

        System.out.println("\n===This is a pig===");
        IAnimal pig = new Pig();
        pig.eat();
        pig.run();
        pig.sleep();
        pig.speak();
    } 
}

 java中的interface

三、爲什麼要使用接口?

歸一化的好處在於:

1)歸一化讓使用者無需關心對象的類是什麼,只須要的知道這些對象都具有某些功能就能夠了,這極大地下降了使用者的使用難度;

2)歸一化使得高層的外部使用者能夠不加區分的處理全部接口兼容的對象集合;

就好象linux的泛文件概念同樣,全部東西均可以當文件處理,沒必要關心它是內存、磁盤、網絡仍是屏幕(固然,對底層設計者,固然也能夠區分出「字符設備」和「塊設備」,而後作出針對性的設計:細緻到什麼程度,視需求而定)。

再好比:咱們有一個汽車接口,裏面定義了汽車全部的功能,而後由本田汽車的類,奧迪汽車的類,大衆汽車的類,他們都實現了汽車接口,這樣就好辦了,你們只須要學會了怎麼開汽車,那麼不管是本田,仍是奧迪,仍是大衆咱們都會開了,開的時候根本無需關心我開的是哪一類車,操做手法(函數調用)都同樣;

四、模仿java中的interface

在python中根本就沒有一個叫作interface的關鍵字,若是非要去模仿接口的概念

能夠藉助第三方模塊:http://pypi.python.org/pypi/zope.interface

也可使用繼承,其實繼承有兩種用途

一:繼承基類的方法,而且作出本身的改變或者擴展(代碼重用):實踐中,繼承的這種用途意義並不很大,甚至經常是有害的。由於它使得子類與基類出現強耦合;

二:聲明某個子類兼容於某基類,定義一個接口類(模仿java的Interface),接口類中定義了一些接口名(就是函數名)且並未實現接口的功能,子類繼承接口類,而且實現接口中的功能;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/16 0016 22:12
#抽象類的概念引入及應用場景;
import abc

class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod#經過抽象類,來實現標準化;
    def run(self):
        pass

    @abc.abstractmethod
    def eat(self):
        pass

class People(Animal):
#    pass#TypeError: Can't instantiate abstract class People with abstract methods eat, run
    def run(self):
        print('People is running')
    def eat(self):
        print('People is eating')
class Pig(Animal): def run(self): print('People is running') def eat(self): print('People is eating') class Dog(Animal): def run(self): print('People is running') def eat(self): print('People is eating') #類實例化產生對象; peo1 = People() pig1 = Pig() dog1 = Dog() # peo1.eat() pig1.eat() dog1.eat() "" """ People is eating People is eating People is eating 小結: 一、抽象類的本質仍是一個類; 二、抽象類與類仍是有一點兒區別的,抽象類只能被繼承,不能被實例化,功能是爲了規範子類; 三、抽象類的做用是基於繼承演變而來的,作歸一化的好處,把全部的接口都規範起來,下降使用者的使用複雜度; """ #抽象類的概念引入及應用場景; #animal = Animal()#TypeError: Can't instantiate abstract class Animal with abstract methods eat, run

18-多態與多態性

一、多態與多態性初識;

1)多態;

多態指的是一類事物有多種形態,好比:動物有多種形態:人,狗,豬;

文件有多種形態:文本文件,可執行文件;

2)多態性;

一 什麼是多態動態綁定(在繼承的背景下使用時,有時也稱爲多態性);

多態性是指在不考慮實例類型的狀況下使用實例,多態性分爲靜態多態性和動態多態性;

靜態多態性:如任何類型均可以用運算符+進行運算;

動態多態性:以下

peo=People()
dog=Dog()
pig=Pig()

#peo、dog、pig都是動物,只要是動物確定有talk方法
#因而咱們能夠不用考慮它們三者的具體是什麼類型,而直接使用
peo.talk()
dog.talk()
pig.talk()

#更進一步,咱們能夠定義一個統一的接口來使用
def func(obj):
    obj.talk()

二、 爲何要用多態性(多態性的好處)

python自己就是支持多態性的,這麼作的好處是什麼呢?

1)增長了程序的靈活性

  以不變應萬變,不論對象變幻無窮,使用者都是同一種形式去調用,如func(animal);

2)增長了程序額可擴展性

 經過繼承animal類建立了一個新的類,使用者無需更改本身的代碼,仍是用 func(animal)去調用 ;

三、鴨子類型

Python崇尚鴨子類型,即‘若是看起來像、叫聲像並且走起路來像鴨子,那麼它就是鴨子;

python程序員一般根據這種行爲來編寫程序。例如,若是想編寫現有對象的自定義版本,能夠繼承該對象;

也能夠建立一個外觀和行爲像,但與它無任何關係的全新對象,後者一般用於保存程序組件的鬆耦合度;

利用標準庫中定義的各類‘與文件相似’的對象,儘管這些對象的工做方式像文件,但他們沒有繼承內置文件對象的方法;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/16 0016 22:43
#多態,同一種事物的多種形態
""
"""
一、水的多種形態;
二、動物的多種形態;
三、文件的多種形態;
"""

import abc
class Animal(metaclass=abc.ABCMeta): #同一類事物:動物
    @abc.abstractmethod
    def talk(self):
        pass

class People(Animal): #動物的形態之一:人
    def talk(self):
        print('say hello')

class Dog(Animal): #動物的形態之二:狗
    def talk(self):
        print('say wangwang')

class Pig(Animal): #動物的形態之三:豬
    def talk(self):
        print('say aoao')

class Cat(Animal):#貓
    def talk(self):
        print('say miaomiao')
#多態性-指的是能夠在不考慮對象的類型下而直接使用對象;
peo1 = People()
dog1 = Dog()
pig1 = Pig()
cat1 = Cat()

peo1.talk()
dog1.talk()
pig1.talk()
cat1.talk()
#靜態多態性;
#動態多態性;
def func(animal):
    animal.talk()
func(peo1)
func(pig1)
func(dog1)
func(cat1)
#Python崇尚鴨子類型;
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/16 0016 22:55
#鴨子類型引入;
class File:
    def read(self):
        pass
    def write(self):
        pass

class Disk: def read(self): print('disk read') def write(self): print('disk write') class Text: def read(self): print('text read') def write(self): print('text write') disk = Disk() text = Text() disk.read() disk.write() text.read() text.write() #序列類型——列表list、元組tuple、字符串str; l = list([1,2,3]) t = tuple(('a','b')) s = str('hello') print(l.__len__()) print(t.__len__()) print(s.__len__()) #按照原來的方法; def len(obj): return obj.__len__() print(len(l)) print(len(t)) print(len(s))

19-封裝之如何隱藏屬性

一、封裝概念初識;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/17 0017 14:34
class A:
    __X=1#_A__x=1,在定義階段就被定義;
    def __init__(self,name):#self._A__name = name
        self.__name = name
    def __foo(self):
            print('run foo')
    def bar(self):
        self.__foo()#self._A__foo()
        print('from bar')
#print(A.__X)#AttributeError: type object 'A' has no attribute '__X'
#print(A.__foo)#AttributeError: type object 'A' has no attribute '__foo'
a = A('egon')
#print(a.__name)#AttributeError: 'A' object has no attribute '__name'
print(a.__dict__)#{'_A__name': 'egon'}
"""
這種變形的特色:
一、外部沒法直接訪問obj.__AttrName;
二、在類內部是能夠直接使用:obj.AttrName
三、子類沒法覆蓋父類__開頭的屬性;
"""
class Foo:
    def __func(self):#_Foo__func
        print('from foo')
class Bar(Foo):
    def __func(self):#_Bar__func
        print('from bar')
#b = Bar()
#b.func()
"""
總結這樣的變形須要注意的問題:
一、
"""
class B:
    __x = 1
    def __init__(self,name):
        self.__name = name#類定義階段發生隱藏;
#驗證問題1:
#print(B._B__x)#1,雖然能正常打印,可是不建議這麼使用,由於這種形式就是Python在作隱藏;
#驗證問題2;
# B.__y =2
# print(B.__dict__)#{'__module__': '__main__', '_B__x': 1, '__init__': <function B.__init__ at 0x00000216F511C048>, '__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__doc__': None, '__y': 2}
# b = B('egon')
# print(b.__dict__)#{'_B__name': 'egon'}
#print(B.__x)#AttributeError: type object 'B' has no attribute '__x'
#驗證問題3:
# class A:
#     def  foo(self):
#         print('A.bar')
#     def bar(self):
#         print('A.bar')
#         self.foo()
# class B(A):
#     def foo(self):
#         print('B.foo')
#
# b = B()
# b.bar()
"""
A.bar
B.foo
"""

class A:
    def  __foo(self):
        print('A.bar')
    def bar(self):
        print('A.bar')
        self.__foo()
class B(A):
    def __foo(self):
        print('B.foo')

b = B()
b.bar()
"""
A.bar
A.bar
"""

20-封裝的意義

一、爲何要封裝?

1)咱們的身體沒有一處不體現着封裝的概念:你的身體把膀胱尿道等等這些尿的功能隱藏了起來,而後爲你提供一個尿的接口就能夠了(接口就是你的丁丁)你總不能把膀胱掛在身體外面,上廁所的時候就跟別人炫耀:hi,man,你瞅個人膀胱,看看我是怎麼尿的。

2)電視機自己是一個黑盒子,隱藏了全部細節,可是必定會對外提供了一堆按鈕,這些按鈕也正是接口的概念,因此說,封裝並非單純意義的隱藏;

3)快門就是傻瓜相機爲傻瓜們提供的方法,該方法將內部複雜的照相功能都隱藏起來了;

提示:在編程語言裏,對外提供的接口(接口可理解爲了一個入口),能夠是函數,稱爲接口函數,這與接口的概念還不同,接口表明一組接口函數的集合體。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/17 0017 15:15
#封裝數據屬性;明確的區份內外,控制外部對隱藏屬性的操做行爲;
class People:
    def __init__(self,name,age):
        self.__name = name
        self.__age = age
    def tell_info(self):
        print('Name:<%s> Age:<%s>'%(self.__name,self.__age))
    #開通一個接口,可修改name或age 的值;
    def set_info(self,name,age):
        if not isinstance(name,str):
            print('名字必須是字符串類型')
            return
        elif not isinstance(age,int):
            print('年齡必須是數字類型')
            return
        self.__name = name
        self.__age = age

p = People('egon',18)
p.tell_info()#Name:<egon> Age:<18>

p.set_info('EGON',18)
p.tell_info()#Name:<EGON> Age:<18>
#傳入不合法的值;
p.set_info(1993,26)#名字必須是字符串類型
p.tell_info()
#封裝方法:隔離複雜度;用傻瓜相機來對比專業單反,來解釋複雜度,對用戶來說,使用特別簡答;
class Atm:
    def __card(self):
        print('插卡')
    def __auth(self):
        print('用戶認證')
    def __input(self):
        print('輸入提款金額')
    def __bill(self):
        print('打印帳單')
    def __take_money(self):
        print('取款')

    #進行隱藏屬性;
    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__bill()
        self.__take_money()
a = Atm()
a.withdraw()
"""
插卡
用戶認證
輸入提款金額
打印帳單
取款
"""

21-封裝與可拓展性

一、可拓展性舉例;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/17 0017 15:40
#封裝帶來的可拓展性;很是的靈活去拓展功能,可是對於使用者來講,是隱藏的;
class Room:
    def __init__(self,name,owner,weight,length,height):
         self.name = name
         self.owner = owner

         self.__weight = weight
         self.__length = length
         self.__height = height
    def tell_area(self):
             return self.__weight * self.__length * self.__height
r = Room('衛生間','alex',10,10,3)
r.tell_area()
print(r.tell_area())#300 立方米;

22-Property的使用

一、使用property方法的優勢介紹;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/17 0017 18:01
#體質指數(BMI)= 體重(kg)/身高*身高(m)
class People:
    def __init__(self,name,weight,height):
        self.name = name
        self.weight = weight
        self.height = height
    #定義一個新函數bmi;
    #添加一個property裝飾器屬性;
    @property
    def bmi(self):
        return self.weight / (self.height ** 2)
#實例化產生對象;
p = People('tqtl',110,1.85)
#以下方法太僵化,重複調用;
#p.bmi=p.weight / (p.height ** 2)
#print(p.bmi)#32.14024835646457
#直接調用函數;
#print(p.bmi())#32.14024835646457,雖然實現了功能,可是由原來的「名詞性質調用」變成了「動詞性質的調用」;
#最好的調用方法;
print(p.bmi)#32.14024835646457
"""
一、添加了property屬性後,恢復到以前的名詞調用方式,相對於使用print(p.bmi())方式,給用戶的感受沒有發生變化;
"""
#新增需求,自定義了身高指數
p.height = 1.90
print(p.bmi)#30.470914127423825
#可是不能爲p.bmi屬性賦值,由於他是動態計算出來的,會報錯;
#p.bmi = 38
#print(p.bmi)#AttributeError: can't set attribute;


#補充property的用法;
class People:
    def __init__(self,name):
        self.__name = name
    # @property
    # def get_name(self):
    #     return self.__name
    @property#使用property的好處,至關於作了一個假裝,將動詞屬性的調用方式,改成名詞屬性的調用方式;
    def name(self):
        return self.__name

    #爲了實現賦值功能,再次定義;
    @name.setter
    def name(self,val):
        if not isinstance(val,str):
            print('名稱必須是字符串')
            return
        self.__name =val
    #實現刪除操做;
    @name.deleter
    def name(self):
        print('不容許刪除')


#實例化產生對象;
p = People('tqtl')
#print(p.get_name)#tqtl

#新需求,不想讓用戶使用p.get_name,使用者容易形成誤解,怎麼辦?使用property裝飾器;
print(p.name)#tqtl
#不能直接賦值;p.name = 'TQTL',如何解決?不太經常使用;
p.name = 'TQTL'
print(p.name)#TQTL,實現了從新賦值操做;
#新需求又來了,如何定義刪除功能呢?同上
del p.name#不容許刪除
print(p.name)

23-綁定與非綁定方法介紹

一、綁定與非綁定方法詳解;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:python3.6.5
# Date:2018/6/17 0017 20:17
""
"""
在類內部定義的函數,分爲兩大類:
1、綁定方法:綁定給誰,就應該由誰來調用,誰來調用,就會把調用者當作第一個參數自動傳入;

1)綁定到對象的方法:在類內定義的沒有被任何裝飾器修飾的;
2)綁定到類的方法:在類內部定義的,被裝飾器classmethod修飾的方法;

2、非綁定方法:沒有自動傳值這麼一說;就類中定義的一個普通工具,對象和類均可以使用;使用staticmethod關鍵字;
   非綁定方法:不與類或者對象綁定:
"""
#實例演示:
class Foo:
    def __init__(self,name):
        self.name = name
    def tell(self):
        print('名字是%s'%self.name)

    @classmethod
    def func(cls):#cls = Foo
        print(cls)
        
    @staticmethod#真正意義上的普通函數;
    def func1(x,y):
        #return x + y
        print(x+y)
f = Foo('tqtl')
# print(Foo.tell)#<function Foo.tell at 0x0000015F867A0D90>
# Foo.tell(f)#名字是tqtl
# print(f.tell)#名字是tqtl
#print(Foo.func)#<bound method Foo.func of <class '__main__.Foo'>>
#Foo.func()#<class '__main__.Foo'>
#print(Foo)#<class '__main__.Foo'>
print(Foo.func1)#<function Foo.func1 at 0x00000276CAC20E18>
print(f.func1)#<function Foo.func1 at 0x00000276CAC20E18>

Foo.func1(1,2)#3
f.func1(1,3)#4

24-綁定方法與非綁定方法的使用

一、應用場景講解;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/17 0017 20:37
import settings
import hashlib
import time
class People:
    def __init__(self,name,age,sex):
        self.id = self.create_id()
        self.name = name
        self.age = age
        self.sex = sex
    def tell_info(self):#綁定到對象的方法;
        print('Name:%s Age:%s Sex:%s'%(self.name,self.age,self.sex))

    @classmethod
    def from_conf(cls):
        obj = cls(
            settings.name,
            settings.age,
            settings.sex,
        )
        return obj#必定有return返回值;
    
    @staticmethod#使用該關鍵字,聲明函數爲基本函數;
    def create_id():
        m = hashlib.md5(str(time.time()).encode('utf-8'))#使用str()方法將時間轉換爲字符串,由於不可變數據類型纔可被hash;
        return m.hexdigest()

#實例化產生對象;
p = People('tqtl',18,'male')
#綁定給對象,就應該由對象來調用,自動將對象自己當作第一個參數傳入;
#p.tell_info() #tell_info(p)
#綁定給類,就應該由類來調用,自動將類自己當作第一個參數傳入;
p = People.from_conf()
p.tell_info()#Name:alex Age:18 Sex:female
#非綁定方法,不與類或者對象綁定,誰均可以調用,沒有自動傳值一說;

#開始實例化產生對象;
p1 = People('egon',18,'male')
p2 = People('alex',28,'female')
p3 = People('peiqi',38,'female')
p4 = People('tqtl',8,'male')
print(p1.id)#1ca14d661c87f8cf51e12f0250ea9f14
print(p2.id)#1ca14d661c87f8cf51e12f0250ea9f14
print(p3.id)#1ca14d661c87f8cf51e12f0250ea9f14
print(p4.id)#1ca14d661c87f8cf51e12f0250ea9f14

25-反射

一、反射的實際應用;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/17 0017 20:57
#經過字符串,映射到對象的屬性;
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print('%s is talking'%self.name)

obj = People('tqtl',18)
#print(obj.name)#tqtl
#print(obj.talk)#<bound method People.talk of <__main__.People object at 0x000001C1FB49FA20>>

#choice = input('>>>:')#choice = 'name'
#print(obj.choice)#print(obj.'name')#這麼寫語法錯誤;


#hasattr()
hasattr(obj,'name')#obj.name
print(hasattr(obj,'name'))#True
print(hasattr(obj,'talk'))#True

getattr(obj,'name')
getattr(obj,'name',None)
print(getattr(obj,'name'))#tqtl
print(getattr(obj,'talk',None))#<bound method People.talk of <__main__.People object at 0x00000133664749B0>>

setattr(obj,'sex','male')
print(obj.sex)#male

delattr(obj,'age')
print(obj.__dict__)#{'name': 'tqtl', 'sex': 'male'}


#經過字符串來訪問到對象或類的屬性的一種方法;
#具體應用場景-反射應用
class Service:
    def run(self):
        while True:
            inp = input('>>>:').strip()#cmd = 'get a.txt'
            cmds = inp.split()#cmds = ['get','a.txt']
            #print(cmds)
            if hasattr(self,cmds[0]):
                func = getattr(self,cmds[0])
                func(cmds)
            # cmd = input('>>>').strip()
            # print(cmd)

    def get(self,cmds):#下載功能;
        print('get ...',cmds)

    def put(self,cmds):#上傳功能;
        print('put ...',cmds)

obj = Service()
obj.run()

"""
>>>:get a.txt
get ... ['get', 'a.txt']
>>>:put a.txt
put ... ['put', 'a.txt']
>>>:
"""

26-內置方法介紹

一、內置方法詳解(_item__\__str__\__del__);

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/17 0017 21:20
#item系列;
class Foo:
    def __init__(self,name):
        self.name = name

    def __getitem__(self, item):
        #print('getitem')
       # print(item)
        return self.__dict__.get(item)
    def __setitem__(self, key, value):
        #print('setitem')
        #print(key,value)
        self.__dict__[key] = value
    def __delitem__(self, key):
        #print('delitem')
        #print(key)
        #self.__dict__.pop()
        del self.__dict__[key]
obj = Foo('tqtl')
#查看屬性;
#obj['name']#完成obj.name
print(obj['namexxxx'])#None
#設置屬性;
obj.sex = 'male'
obj['sex']='male'
print(obj.__dict__)
print(obj.sex)#male

#刪除屬性;
#以前的套路:
#del obj.name
#如今的套路;
del obj['name']
print(obj.__dict__)#male
"""
小結:
把對象作成一個像字典同樣的對象去操做;
把類定製化成dict類型的東西,進行增刪改查操做;
"""

d = {'name':'tqtl'}
print(isinstance(d,dict))#True



#__str__方法;
class People:
    def __init__(self,name,age):
        self.name =name
        self.age = age
    def __str__(self):
        #print('=====>str')#TypeError: __str__ returned non-string (type NoneType)
        return '<name:%s,age:%s>'%(self.name,self.age)
obj = People('tqtl',26)
#print(obj)#<__main__.People object at 0x000001CD512E4BE0>
print(obj)#<name:tqtl,age:26>
#print語句,打印對咱們有用的信息;


#__del__方法;回收系統資源
# f = open(file='settings.py',mode='rb')#本質上是一個賦值操做;
# f.read()
# f.close()#申請的資源,用完以後,要回收;給操做系統發送信號,回收操做系統資源;
# print()
class Open:
    def __init__(self,filename):
        print('Open file......')
        self.filename = filename

    def __del__(self):
        print('回收操做系統資源:self.close()')
f = Open('settings.py')
print('----main-----')#
"""
Open file......
----main-----
回收操做系統資源:self.close()
"""

27-元類介紹

一、元類概念初識以及原理剖析;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/17 0017 22:34
""
"""
知識儲備:exec
一、參數1:字符串形式的命令;
二、參數2:全局做用域(字典形式),若是不指定,默認就使用globals()
三、參數3:局部做用域(字典形式),若是不指定,默認就使用locals()
"""
# g = {
#     'x':1,
#     'y':2
# }
# l = {}
# exec("""
# global x,m
# x = 10
# m =100
#
# z =3
# """,g,l)
# print(g)
# print(l)
"""
C:\\Users\\Administrator\PycharmProjects\LFXC2018\venv\Scripts\python.exe "C:/Users/Administrator/PycharmProjects/LFXC2018/第三模塊 面向對象/27-元類介紹.py"
{'x': 10, 'y': 2, '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'Exception': <class 'Exception'>, 'TypeError': <class 'TypeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'GeneratorExit': <class 'GeneratorExit'>, 'SystemExit': <class 'SystemExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'ImportError': <class 'ImportError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'OSError': <class 'OSError'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'WindowsError': <class 'OSError'>, 'EOFError': <class 'EOFError'>, 'RuntimeError': <class 'RuntimeError'>, 'RecursionError': <class 'RecursionError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'IndentationError': <class 'IndentationError'>, 'TabError': <class 'TabError'>, 'LookupError': <class 'LookupError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ValueError': <class 'ValueError'>, 'UnicodeError': <class 'UnicodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'AssertionError': <class 'AssertionError'>, 'ArithmeticError': <class 'ArithmeticError'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'SystemError': <class 'SystemError'>, 'ReferenceError': <class 'ReferenceError'>, 'BufferError': <class 'BufferError'>, 'MemoryError': <class 'MemoryError'>, 'Warning': <class 'Warning'>, 'UserWarning': <class 'UserWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'BytesWarning': <class 'BytesWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'ConnectionError': <class 'ConnectionError'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'InterruptedError': <class 'InterruptedError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-Z plus Return to exit, 'exit': Use exit() or Ctrl-Z plus Return to exit, 'copyright': Copyright (c) 2001-2018 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved., 'credits':     Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
    for supporting Python development.  See www.python.org for more information., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.}, 'm': 100}
{'z': 3}

Process finished with exit code 0

"""
#Python中一切皆對象;對象能夠怎麼使用呢?
"""
一、均可以被引用;
二、均可以當作函數的參數傳入;
三、均可以當作容器類的元素;
四、均可以當作函數的返回值;
五、從Python一切皆對象的角度來看,那麼類也是對象;
"""
#什麼叫元類?!
class Foo:
    pass
obj = Foo()
print(type(obj))#<class '__main__.Foo'>
print(type(Foo))#<class 'type'>
class Bar:
    pass
print(type(Bar))#<class 'type'>
"""
小結:
一、產生類的類,稱之爲元類,默認所使用class關鍵字定義的類,他們的元類是type;
"""
#二、定義類的兩種方式;
#方式一:class關鍵字;
class Chinese:
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print('%s is talking'%self.name)
print(Chinese)#<class '__main__.Chinese'>
#方式二:type關鍵字
#定義類的三要素;類名、類的基類們,類的名稱空間;
class_name = 'Chinese'
class_bases = (object,)
class_body = """
def __init__(self,name,age):
    self.name = name
    self.age = age
def talk(self):
    print('%s is talking'%self.name)
"""
class_dic = {}
exec(class_body,globals(),class_dic)
print(class_dic)#{'__init__': <function __init__ at 0x000002BCE6762E18>, 'talk': <function talk at 0x000002BCE86E0A60>}

Chinese1=type(class_name,class_bases,class_dic)
print(Chinese1)#<class '__main__.Chinese'>

obj1 = Chinese1('tqtl',25)
print(obj1,obj1.name,obj1.age)#<__main__.Chinese object at 0x0000017351444BA8>tqtl 25

28-自定義元類控制類的建立

一、自定義元類控制控制類詳解;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/17 0017 23:09

#如何本身定製元類;
class Mymeta(type):#自定義元類,要繼承type;
    def __init__(self,class_name,class_bases,class_dic):
        if not class_name.istitle():
            raise TypeError('類名的首字母必須大寫')
        if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise TypeError('必須有註釋且不能爲空;')#拋出異常;
            #主動拋出異常關鍵字raise;
        print(class_dic)
        #print(class_name)#Chinese
       # print(class_bases)#(<class 'object'>,)
        #print(class_dic)#{'__module__': '__main__', '__qualname__': 'Chinese', 'country': 'China', '__init__': <function Chinese.__init__ at 0x0000020E7C740D90>, 'talk': <function Chinese.talk at 0x0000020E7C740A60>}

        super(Mymeta,self).__init__(class_name,class_bases,class_dic)


#class chinese(object,metaclass=Mymeta):#TypeError: 類名的首字母必須大寫
class Chinese(object,metaclass=Mymeta):
    '''
    這裏是註釋哦,出現了__doc__': '\n    這裏是註釋哦\n    '
    '''
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print('%s is talking'%self.name)
#Chinese = type(class_name,class_bases,class_dic)
#raise TypeError('類型錯誤')

"""
小結:
一、自定義元類控制建立類的屬性;
"""

class Foo:
    pass
print(Foo.__dict__)#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}

29-自定義元類與控制類的實例化行爲

一、自定義元類控制實例化行爲詳解;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/17 0017 23:33
""
"""
#知識儲備__call__方法;
class Foo:
    def __call__(self,*args,**kwargs):
        print(self)
        print(args)
        print(kwargs)
obj = Foo()#()
#obj()#{}
obj(1,2,3,a=1,b=2,c=4)#{'a': 1, 'b': 2, 'c': 4}
#元類內部也應該有一個__call__方法,會在調用Foo時候出發執行;
"""

class Mymeta(type):#自定義元類,要繼承type;
    def __init__(self,class_name,class_bases,class_dic):
        if not class_name.istitle():
            raise TypeError('類名的首字母必須大寫')
        if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise TypeError('必須有註釋且不能爲空;')#拋出異常;
            #主動拋出異常關鍵字raise;
        print(class_dic)
        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    #定製call方法;
    def __call__(self, *args, **kwargs):
        print(self)
        print(args)
        print(kwargs)
        print('======>')
        #第一件事:先造一個空對象obj;obj
        obj = object.__new__(self)
       # Chinese.__init__(obj.*args.**kwargs)
        # 第二件事:初始化obj;
        self.__init__(obj,*args,**kwargs)
        #第三件事:返回obj;
        return obj
class Chinese(object,metaclass=Mymeta):
    '''
    這裏是註釋哦,出現了__doc__': '\n    這裏是註釋哦\n    '
    '''
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print('%s is talking'%self.name)
obj = Chinese('tqtl',18)#至關於:Chinese.__call__(Chiese,'tqtl',18)#======>
obj2 = Chinese('tqtl',age=18)#{'age': 18}#======>
#在Chinese('tqtl',18)內部產生三件事;
#一、先造出空對象obj;
#二、初始化obj;
#三、返回obj;

30-自定義元類與控制類的實例化行爲的應用

一、代碼舉例,雖然說有些抽象,先記錄下;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/18 0018 9:20
#單例模式
#實現方式一:
class Mysql:
    __instance = None
    def __init__(self):
        self.host = '127.0.0.1'
        self.port = 3306
    @classmethod
    def singleton(cls):
        if not cls.__instance:
            obj = cls()
            cls.__instance = obj
        return cls.__instance
    def conn(self):
        pass
    def execute(self):
        pass


# obj1 = Mysql()
# obj2 = Mysql()
# obj3 = Mysql()
# print(obj1)
# print(obj2)
# print(obj3)
obj1 = Mysql.singleton()
obj2 = Mysql.singleton()
obj3 = Mysql.singleton()
print(obj1 is obj2)#True
print(obj1 is obj3)
print(obj2 is obj3)


#實現方式二:元類的方式
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        if not class_name.istitle():
            raise TypeError('類名首字母必須大寫')
        elif '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise TypeError('必須有註釋,且註釋不能爲空')
        super(Mymeta, self).__init__(class_name,class_bases,class_dic)#繼承父類的屬性;
        self.__instance=None

    def __call__(self,*args,**kwargs):
        if not self.__instance:
            obj = object.__new__(self)
            self.__init__(obj)
            self.__instance=obj
        #obj = object.__new__(self)
        #self.__init__(obj,*args,**kwargs)
        return self.__instance


class Mysql(object,metaclass=Mymeta):
    '''
    連接MySQL老數據
    '''
    def __init__(self):
        self.host = '127.0.0.1'
        self.port = 3306
    @classmethod
    def singleton(cls):
        if not cls.__instance:
            obj = cls()
            cls.__instance = obj
        return cls.__instance
    def conn(self):
        pass
    def execute(self):
        pass

obj1 = Mysql()
obj2 = Mysql()
obj3 = Mysql()
print(obj1 is obj2 is obj3)#True
"""
小結:
一、元類是面向對象當中一個深層次的方法,先定義爲選學內容;
"""

31-面向對象的軟件開發與做業介紹

一、博文參考;

http://www.cnblogs.com/linhaifeng/articles/7341318.html

32-什麼是異常處理

一、什麼是異常?!

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/18 0018 9:56
""
"""
什麼是異常?!異常時錯誤發生的信號,一旦程序發生錯誤,而且程序沒有處理這個錯誤,那個就會拋出異常,而且程序的運行隨之終止;

錯誤分爲兩種:
一、語法錯誤;在程序執行前就要馬上改正過來;
二、邏輯錯誤;
"""
#No.001-ValueError: invalid literal for int() with base 10: 'cuixiaozhao'
#int('cuixiaozhao')
#No.002-NameError: name 'name' is not defined
#name

#No.003-IndexError: list index out of range
#list1 = [1,2,3]
#list1[1000]

#No.004-KeyError: 'name'
#dict1 = {}
#dict1['name']

#No.005-AttributeError: type object 'Foo' has no attribute 'cxz'
#class Foo:
#    pass
#Foo.cxz

#No.006-ZeroDivisionError: division by zero
#1/0

#No.007-TypeError: 'int' object is not iterable
#for i in 3:
#    print(i)

#No.008-ModuleNotFoundError: No module named 'cuixiaozhao'
#import cuixiaozhao

#No.009-被終止;
#import time
#time.sleep(1000)

"""
一、如何進行異常處理?!
強調1:若是錯誤發生的條件是能夠預知的,此時應該使用if判斷去預防異常;
強調2:若是錯誤發生的條件是不能夠預知的,此時應該使用異常處理機制,try ... except
"""
try:#表示監測代碼;
    with open(file='a.txt',mode='r',encoding='utf-8') as f:
        #next(f)
        print(next(f),end='')
        print(next(f),end='')
        print(next(f),end='')
        print(next(f),end='')
        print(next(f),end='')
        print(next(f),end='')


        print(next(f),end='')
        print(next(f),end='')
        print(next(f),end='')
        print(next(f),end='')
except StopIteration:
    print('出錯啦!')
print('=========>1')
print('=========>2')
print('=========>3')
print('=========>4')
print('=========>5')

33-try...except...詳細用法

一、異常處理的使用說明及try...except的詳解;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __Author__:Administrator
# Version:Python3.6.5
# Date:2018/6/18 0018 10:21

#異常的多分支;被監測的代碼塊,有可能會拋出異常,有多重可能性,而且咱們須要針對每一種異常類型,都定製專門的處理邏輯;
# try:
#     print('========>1')
#     #name
#     print('========>2')
#     list1 = [1,2,3]
#     #list1[100]
#     print('========>3')
#     dict1 = {}
#     dict1['name']
#     print('========>3')
# except NameError as e:
#     print('-=----------',e)#-=---------- name 'name' is not defined
# except IndexError as e:
#     print('-->',e)
# except KeyError as e:
#     print('---------->',e)
#print('繼續執行下一個模塊的代碼;')


#萬能異常:Exception:被監測的代碼塊,有可能會拋出異常,有多重可能性,而且咱們須要針對每一種異常類型,都定製專門的處理邏輯;
#應用場景:咱們針對全部的異常類型,都只用一種處理邏輯就能夠啦!
try:
    print('========>1')
    name
    print('========>2')
    list1 = [1,2,3]
    list1[100]
    print('========>3')
    dict1 = {}
    dict1['age']
    print('========>4')
except Exception as e:
    print('異常發生啦!',e)

print('繼續執行下一個模塊的代碼;')



#異常多分支與萬能異常的綜合運用;
try:
    print('========>1')
    name
    print('========>2')
    list1 = [1,2,3]
    list1[100]
    print('========>3')
    dict1 = {}
    dict1['name']
    print('========>3')
except NameError as e:
    print('-=----------',e)#-=---------- name 'name' is not defined
except IndexError as e:
    print('-->',e)
except KeyError as e:
    print('---------->',e)
except Exception as e:
    print('Exception是統一的處理方法',e)
print('繼續執行下一個模塊的代碼;')

#異常處理的其餘結構;
try:
    print('========>1')
    name
    print('========>2')
    list1 = [1,2,3]
    list1[100]
    print('========>3')
    dict1 = {}
    dict1['name']
    print('========>3')
except NameError as e:
    print('-=----------',e)#-=---------- name 'name' is not defined
except IndexError as e:
    print('-->',e)
except KeyError as e:
    print('---------->',e)
except Exception as e:
    print('Exception是統一的處理方法',e)
else:
    print('在被檢測的代碼沒有發生異常時候執行')
finally:
    print('無論被監測的代碼塊有沒有誤發生異常,都會執行!')#好比打開文件的操做,無論有沒有出錯,都應該使用f.close()進行關閉文件,此時就用到
print('繼續執行下一個模塊的代碼;')

#主動出發異常,raise,異常類型(值)
class People:
    def __init__(self,age,name):
        if not isinstance(name,str):
            raise TypeError('名字必須傳入str類型')
        elif not isinstance(age,int):
            raise TypeError('年齡必須傳入int類型')
        self.name = name
        self.age = age

#p1 = People(333,18)
#p2 = People('cuixiaozhao',18)
#p3 = People('lijingping','18')


#斷言assert
info = {}
info['name'] = 'tqtl'
#info['age'] = 26

# if 'name' not in info:
#     raise KeyError('必須有name這個key')
# if 'age' not in info:
#     raise KeyError('必須有age這個key')

#assert ('name' in info) and ('age' in info)#取代以上代碼;AssertionError


#自定義異常,即自定義類;
class MyException(BaseException):
    def __init__(self,msg):
        super(MyException,self).__init__()
        self.msg = msg

    def __str__(self):
        return '<%s>'%self.msg
raise MyException('我自定義的異常類型哦!')#    raise MyException('我自定義的異常類型哦!')
#__main__.MyException: <我自定義的異常類型哦!>


""
"""
千萬不要把異常處理當作萬能的,不要依賴異常處理;
使用場景:
一、錯誤必定會發生,可是沒法預知,並且不能由於錯誤發生而終止程序的運行,即便用異常處理,進行拋出異常操做;
二、錯誤自己可預知,好比if判斷,不該該使用異常處理;
"""
相關文章
相關標籤/搜索