python中的對象與類

一,嵌套函數
要點:內部函數只能在函數內被使用,在函數外不可以被使用
使用情況:(1)封裝,數據隱藏。(2)避免重複代碼(3)閉包情況使用
嵌套函數示例如下:

#嵌套函數

def outer():
    print('ourer running')
    def inner01():
        print('inner running')
    inner01()
outer()


def printname(ischinese,name,familyname):
    def inner(a,b):
        print('{0}{1}'.format(a,b))
    if ischinese==0:
        inner(name,familyname)
    else:
        inner(familyname,name)
printname(True,'hy','l')
printname(False,'hy','l')
#可分成兩個函數,ischinese,isenglishname來寫,但那樣有重複。

結果如下:

ourer running
inner running
l  hy
hy  l

二,nonlocal關鍵字
nonlocal用來聲明外部的局部變量
global 用來聲明全局變量
這兩個都可以在內部函數正常調用,但是想要修改必須定義
代碼如下:

a=10
def outer():
    b=20
    global a
    a=20
    print(a)
    def inner():
        nonlocal b
        b=30
        print(b)
    inner()
outer()

結果如下:

20
30

三,LEGB規則
python中查找變量名的時候,先在local(函數內部查找),然後在Enclosed(嵌套函數外部查找),然後在global(模塊)查找,最後在Built in(python爲自己保留的特殊名稱中查找)
代碼如下:

print(type(str))
#str='global'

def outer():
    #str='outer'
    def inner():
        #str='inner'
        print(str)
    inner()
outer()

結果爲:

<class 'type'>
<class 'str'>

四,面向對象與對象
python即可以面向對象,又可以面向過程
所謂面向對象編程就是:將數據和操作數據的相關方法封裝在對象內
python中一切皆對象,對象其實就是堆內存內的一個內存塊

五,類
類可分爲方法(函數)與屬性(變量)
對象可分爲:方法(由創建它的類規定好的),屬性(變量)
創建一個類的代碼如下:

class Student:  #類名一般首字母大寫,多個單詞采用駝峯原則
    def __init__(self,name,score):#self必須位於第一個        實例屬性
        self.name=name
        self.score=score
    def say_score(self):
        print('{0}的成績爲{1}'.format(self.name,self.score))
s1=Student('lhy',90)#self默認傳,爲對象的地址。爲創建的Student('lhy',90)對象的地址,通過類名調用構造函數
s1.say_score()
s1.age=18
print(s1.age)

print(dir(s1))
print(s1.__dict__)
print(isinstance(s1,Student))
print(isinstance(s1,int))
print(isinstance(Student,type))

結果如下:

lhy的成績爲90
18
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name', 'say_score', 'score']
{'name': 'lhy', 'score': 90, 'age': 18}
True
False
True

解釋代碼:首先,self其實等於創建實例s1或s2的地址,只是self通概表示所有的對象地址。
class Student 這句代碼創建了一個類對象,這裏後面具體說明。
def init 這句代碼定義的是構造函數。
def say_score 定義的是實例方法,但其實具體代碼保存在類對象中,實例對象中只是指向這個函數的地址,所以實例方法其實爲所有實例共享。

當執行s1=Student(‘lhy’,60)時,其實就是在創建一個實例對象,它先調用
(1)new()方法創建一個對象,不過我們一般無需定義
(2)init()方法將lhy,60,傳進去完成初始化,給實例屬性賦值(self.name=name)這裏發生了,在self內的地址中的name等於形參name,也就是實例對象中的name=形參name,在這裏s1=self

當執行s1.say_score()時調用了實例方法。其實會被翻譯爲Student.say_score(s1)

s1.age是添加了一個實例屬性。如果再定義一個s2,則s2中不存在這個實例對象

dir()獲得對象的所有屬性與方法
s1.__dict__對象的屬性字典
isinstance(s1,Student)判斷s1是否屬於Student類
Student屬於type大類

五,構造函數要點
(1)名稱固定
(2)第一個參數爲self
(3)通過類名(參數列表)調用,調用後將創建好的對象返回
(4)構造函數通常用於初始化實例對象的實例屬性

六,實例屬性
從屬於實例對象的屬性,也稱實例變量
(1)一般在構造函數中定義:
self.name=name
(2)在本類的其他實例方法中,通過self進行訪問
如self.name

七,實例方法
從屬於實例對象的方法
注意:類方法爲所有對象共享,兩個不同的實例對象只要屬於同一類,那麼實例方法的代碼用的是同一個,都在該類中,而對象的空間中只有該方法的地址。

調用實例方法時,不需要也不能給self傳參數

八,函數與方法的區別
(1)方法調用時要通過對象來調用
(2)方法需要self

九,類對象
屬於type大類
代碼如下:

class Student:  #類名一般首字母大寫,多個單詞采用駝峯原則
    def __init__(self,name,score):#self必須位於第一個        實例屬性
        self.name=name
        self.score=score
    def say_score(self):
        print('{0}的成績爲{1}'.format(self.name,self.score))

s=Student
s2=s('lhy',60)
s2.say_score()
Student.say_score(s2)

十,類屬性
從屬於類對象,也稱類變量
代碼如下:

class Student:
    count=0
    company='yzu'#類屬性
    def __init__(self,name,score):
        self.name=name
        self.score=score #實例屬性
        Student.count+=1
    def sayscore(self):
        print('{0}的分數是{1}'.format(self.name,self.score))

s1=Student('lhy',60)#實例對象,自動調用__init__函數
s1.sayscore()
s2=Student('z3',30)
Student.sayscore(s2)
print("一共{0}個人在{1}公司".format(Student.count,Student.company))

結果如下:

lhy的分數是60
z3的分數是30
一共2個人在yzu公司

本例中,student.count與student.company就是類屬性

十一,類方法與靜態方法
類方法:從屬於類對象的方法,用來操作類屬性
通過@classmethod來定義
格式爲:@classmethod
def 類方法名(cls,【形參列表】):
函數體
要點:(1)@classmethod必須在第一行
(2)第一個cls必須有,指向類函數本身
(3)類名.類方法名(參數列表) ,不需要也不能給cls傳值
(4)類方法中訪問實例屬性或方法會報錯
(5)子類繼承父類方法時,傳入cls的是子對象而非父對象。

靜態方法:python中允許定義與類對象無關的方法
格式如下:@staticmethod
def 靜態方法名(【參數列表】)
函數體
在其中也可以 引用類屬性
代碼如下:

class Student:
    company='yzu'
    @staticmethod
    def add(a,b):
        print('{0}+{1}={2}'.format(a,b,a+b))
        print(Student.company)
    @classmethod
    def printc(cls):
        print('公司是',cls.company)#要加Student,也可以加cls


Student.printc()
Student.add(1,2)

結果如下:

公司是 yzu
1+2=3
yzu

從某種含義上來說,cls=Student,但是在調用時,不可以用cls代替Student

十二,析構函數和垃圾回收機制
__del__方法被稱爲析構函數,用來實現對象被銷燬時所需操作
垃圾回收機制:當對象的引用計數爲0時,垃圾回收器調用__del__方法
可以用del刪除對象來確保調用__del__方法
代碼如下:


class none:
    def __del__(self):
        print('被銷燬的對象是{0}'.format(self))
q1=none()
q2=none()
del q2#其實就是調用__del__函數,所以先刪除q2
print(q1)

結果爲

被銷燬的對象是<__main__.none object at 0x000001E0300FD848>
<__main__.none object at 0x000001E0300FD7C8>
被銷燬的對象是<__main__.none object at 0x000001E0300FD7C8>

十三,__call__方法與可調用對象
用__call__方法定義的對象叫做可調用對象,即該對象可以像函數一樣被調用
代碼如下:

class Salary:
    def __call__(self, salary):
        yearsalary=salary*12
        daysalary=salary/30
        hoursalary=daysalary/8
        return dict(hoursalary=hoursalary,daysalary=daysalary,mouthsalary=salary,yearsalary=yearsalary)
    def p(self):
        print('執行了')

s=Salary()
print(s(30000))

結果爲:

{'hoursalary': 125.0, 'daysalary': 1000.0, 'mouthsalary': 30000, 'yearsalary': 360000}

注意前面說的__call__方法與__del__方法是與構造函數一個等級的,他們作用的類創建出來的對象。
在__call__方法中,要注意這一句s=Salary()不能傳參數,參數要在後面傳。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章