成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Python_OOP

tyheist / 1369人閱讀

摘要:魔法方法類構(gòu)造方法魔法方法初始化對(duì)象創(chuàng)建對(duì)象的過程創(chuàng)建一個(gè)對(duì)象解釋器會(huì)自動(dòng)的調(diào)用方法返回創(chuàng)建的對(duì)象的引用,給實(shí)例實(shí)例化執(zhí)行該方法,返回值。當(dāng)引用計(jì)數(shù)為時(shí),該對(duì)象生命就結(jié)束了。

define class

class的三個(gè)組成部分:

類的名稱:類名

類的屬性: 一組數(shù)據(jù)

類的方法:允許對(duì)進(jìn)行操作的方法(行為)

定義
class Student (object):
    pass

class后面定義類名(類名通常是大寫開頭的單詞)
(object),表示該類是從哪個(gè)類繼承下來的

實(shí)例化

創(chuàng)建實(shí)例是通過類名+()實(shí)現(xiàn)

stu = Student()

class Stu (): # 定義class
    age = 10 # 屬性
    def show (self): # 方法
        print(self.age) # 類中獲取屬性
        print(self, "self")
        print(stu.name) # 獲取類外添加屬性

stu = Stu() # 實(shí)例化

stu.name = "sf" # 添加屬性
stu.show() # 調(diào)用方法
self

self當(dāng)前實(shí)例化的對(duì)象
在定義函數(shù)的時(shí)候,第一個(gè)參數(shù)需要self

class Stu ():
    def show_name (self):
        print(self.name)
        
stu = Stu()
stu.name = "sf"

stu.show_name()

self在定義時(shí)需要定義,但是在調(diào)用時(shí)會(huì)自動(dòng)傳入。

self的名字并不是規(guī)定寫死的,但是最好還是按照約定是self。

self總是指調(diào)用時(shí)的類的實(shí)例。

init

魔法方法:

["__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__"]

__init__: 類構(gòu)造方法(魔法方法)

class Stu ():
    # 初始化對(duì)象
    def __init__ (self, new_name, new_age):
        self.name = new_name
        self.age = new_age
    def show (self):    
        print("name: %s, age: %d" % (self.name, self.age))

stu = Stu("sf", 23)
stu.show()

創(chuàng)建對(duì)象的過程:

創(chuàng)建一個(gè)對(duì)象

Python解釋器會(huì)自動(dòng)的調(diào)用__init__方法

返回創(chuàng)建的對(duì)象的引用,給實(shí)例

__str__: 實(shí)例化執(zhí)行該方法,返回值。

當(dāng)需要print一個(gè)類的時(shí)候,需要先在類中定義__str__方法,返回值,就是print()輸出的值

class Stu ():
    def __init__ (self, new_name):
        self.name = new_name
    def __str__ (self):    
        return self.name

__new__: 方法主要是當(dāng)繼承一些不可變的class時(shí)(比如int, str, tuple), 提供一個(gè)自定義這些類的實(shí)例化過程.

class Stu(object):
    def __new__(cls):
        return object.__new__(cls) # 自定義實(shí)例化過程
        # 自身沒有能力創(chuàng)建實(shí)例,可以讓父類創(chuàng)建
    def __init__(self):
        print("init")
stu = Stu()
創(chuàng)建單例對(duì)象
class Single(object):
    __instance = None
    def __new__(cls):
        if cls.__instance != None:
            return cls.__instance
        else:
            cls.__instance = object.__new__(cls)
            return cls.__instance

s1 = Single()
s2 = Single()
私有方法和私有屬性
私有屬性

按照約定俗成的規(guī)定__開頭的屬性表示私有屬性, 不可以直接類名.變量名訪問
在類中存儲(chǔ)的形式為:_Stu__age, _類名__變量名

class Stu():
    def __init__(self, new_name):
        self.name = new_name
        self.__age = 0 # 定義了一個(gè)私有的屬性,屬性的名字是`__age`

在類中訪問形式:self.__變量名

私有方法(private)

按照約定俗成的規(guī)定__開頭的屬性表示私有方法, 不可以直接類名.方法名訪問
存儲(chǔ)的形式為:_Stu__get_age, _類名__方法名

class Stu():
    def __test(self): # 定義私有方法
        pass

在類中調(diào)用私有方法:self.__方法名()

有些時(shí)候,會(huì)看到以一個(gè)下劃線開頭的實(shí)例變量名,比如_name,這樣的實(shí)例變量外部是可以訪問的,但是,按照約定俗成的規(guī)定,當(dāng)看到這樣的變量時(shí),意思就是,“雖然我可以被訪問,但是,請(qǐng)把我視為私有變量,不要隨意訪問”。

del

__del__: 當(dāng)刪除一個(gè)對(duì)象時(shí),python解釋器會(huì)默認(rèn)調(diào)用一個(gè)魔術(shù)方法,__del__()

class Stu():
    def __del__ (self):
        print("remove obj")

stu = Stu()
del stu

在類的生命周期中,如果類銷毀了,python會(huì)自動(dòng)調(diào)用__del__方法。也就是說,不管是手動(dòng)調(diào)用del還是由python自動(dòng)回收都會(huì)觸發(fā)__del__方法執(zhí)行。

對(duì)象引用個(gè)數(shù)

模塊sys中有一個(gè)getrefcount方法可以測(cè)試對(duì)象的引用個(gè)數(shù)
返回的結(jié)果,會(huì)比實(shí)際結(jié)果大1.

import sys

sys.getrefcount("變量/方法")
繼承
class Animal(object):
    def run(self):
        print("Animal is running")

class Dog(Animal): # 繼承
    def run(self):
        print("Dog is running")

class Cat(Animal):
    pass


dog = Dog()
cat = Cat()

dog.run()
cat.run()

當(dāng)子類和父類都存在相同的run()方法時(shí),子類的run()覆蓋了父類的run(),在代碼運(yùn)行的時(shí)候,總是會(huì)調(diào)用子類的run() -- 多態(tài)

重寫

重寫父類的方法,繼承之后,子類定義和父類方法名一樣的方法

class Animal(object):
    def run(self):
        print("Animal is running")

class Dog(Animal):
    def run(self): # 重寫
        print("Dog is running")

class Cat(Animal):
    pass


dog = Dog()
cat = Cat()

dog.run()
cat.run()
調(diào)用父類方法

類名調(diào)用

super關(guān)鍵字調(diào)用

class Animal():
    def run(self):
        print("Animal is running")
class Dog (Animal):
    def say(self):
        #  第一種,類名調(diào)用。
        # Animal.run(self) #方法必須傳遞參數(shù)`self`
        
        # 第二種,super關(guān)鍵字
        super().run()
        print("Gog is running")
 
dog = Dog()
dog.say()        

私有方法,私有屬性在繼承中的表現(xiàn):

私有方法并不會(huì)被繼承(子類外和子類內(nèi)都不會(huì)讓使用)

私有屬性并不會(huì)被繼承(子類外和子類內(nèi)都不會(huì)讓使用)

多繼承

子類具有多個(gè)父類

class A(object): # object是所有最終類的終點(diǎn)
    def test(self):
        print("A")
class B:
    def test(self):
        print("B")

class C(A, B): # 多繼承 (如果繼承類中方法名或者屬性名相同,生效的是參數(shù)先后順序,`類名.__mro__`中的順序)
    pass

print(C.__mro__) 
# (, , , ) 
# C3算法

c = C() # 子類也會(huì)重寫父類的方法
多態(tài)

定義時(shí)的類型和運(yùn)行時(shí)的類型不一樣。

執(zhí)行的時(shí)候確定

class D(object):
    def _print(self):
        print("D")
class X(D):
    def _print(self):
        print("X")

def introduce(temp):
    temp._print()

d = D()
x = X()

introduce(d)
introduce(x)

isinstance()判斷一個(gè)對(duì)象是否是某種類型

實(shí)例屬性屬于各個(gè)實(shí)例所有,互不干擾;
類屬性屬于類所有,所有實(shí)例共享一個(gè)屬性;
不要對(duì)實(shí)例屬性和類屬性使用相同的名字,否則將產(chǎn)生難以發(fā)現(xiàn)的錯(cuò)誤。

類屬性 & 實(shí)例屬性
class A():
    num = 1 # 類屬性
    def __init(self):
        print(self.num)

a = A()
a.name = 100 # 實(shí)例屬性

print(A.num) # 獲取類屬性
實(shí)例方法 & 類方法 & 靜態(tài)方法
class A():
    # 定義類方法
    @classmethod
    def add_num(cls): # 保存類的引用
        pass
    def get_num(self): # 實(shí)例方法
        pass
    @staticmethod
    def set_num(): # 靜態(tài)方法 # 可以沒有任何參數(shù)引用
        pass

a = A()
A.add_num() # 調(diào)用類方法
# a.add_num() # 實(shí)例調(diào)用類方法

A.set_num() # 調(diào)用靜態(tài)方法
a.set_num() # 實(shí)例調(diào)用靜態(tài)方法
私有化

xx: 公有變量
_x: 單前置下劃線,私有化屬性或方法,from somemodule import *禁止導(dǎo)入,類對(duì)象和子類可以訪問
__xx: 雙前置下劃線,避免與子類中的屬性名命名沖突,無法在外部直接訪問
__xx__: 雙前后下劃線,命名空間的魔法對(duì)象或?qū)傩浴?b>__init__。(開發(fā)時(shí),不要使用這種定義變量方式)
xx_: 單后置下劃線,用于避免與Python關(guān)鍵詞的沖突

property

作用:獲取與設(shè)置自動(dòng)調(diào)用方法

類屬性方式調(diào)用property

class Money(object):
    def __init(self):
        pass
    def getMoney(self):
        pass
    def setMoney(self, value):
        pass
    money = property(getMoney, setMoney) # key 為調(diào)用時(shí)候的key

m = Money()
m.money = 10

裝飾器方式使用property

class Money(object):
    def __init__(self):
        self.__num = 0
    @property
    def money(self): # 函數(shù)名和調(diào)用key對(duì)應(yīng) # 獲取
        return self.__money
    @money.setter
    def money(self, value): # 獲取
        self.__num = value

m = Money()
print(m.money)
垃圾回收
小整數(shù)對(duì)象池

作用:為了優(yōu)化速度,使用了小整數(shù)對(duì)象池,避免為整數(shù)頻繁申請(qǐng)和銷毀內(nèi)存空間。

Python對(duì)小整數(shù)的定義是[-5, 257)這些整數(shù)對(duì)象都是提前建立好的,不會(huì)被垃圾回收。在一個(gè)Python的程序中,所有位于這個(gè)范圍內(nèi)的整數(shù)使用的都是同一個(gè)對(duì)象。

單個(gè)字母也是這樣,但是定義2歌相同字符串時(shí),引用計(jì)數(shù)為0,觸發(fā)垃圾回收。

小整數(shù)[-5,257)共用對(duì)象,常駐內(nèi)存

單個(gè)字符共用對(duì)象,常駐內(nèi)存

大整數(shù)對(duì)象池

每一個(gè)大整數(shù),均創(chuàng)建一個(gè)新的對(duì)象。

大整數(shù)不共用內(nèi)存,引用計(jì)數(shù)為0,銷毀

數(shù)值類型和字符串類型在Python中都是不可變的,意味著無法修改這個(gè)對(duì)象的值,每次對(duì)變量對(duì)修改,實(shí)際上是創(chuàng)建一個(gè)新的對(duì)象

intern機(jī)制
a1 = "HelloWorld"
a2 = "HelloWorld"
a3 = "HelloWorld"

intern機(jī)制,讓它只占用一個(gè)”HelloWorld”所占的內(nèi)存空間???strong>引用計(jì)數(shù)去維護(hù)何時(shí)釋放。

單個(gè)單詞,不可修改,默認(rèn)開啟intern機(jī)制,共用對(duì)象,引用計(jì)數(shù)為0,則銷毀

字符串(含有空格),不可修改,沒開啟intern機(jī)制,不共用對(duì)象,引用計(jì)數(shù)為0,銷毀

Garbage collection(GC垃圾回收)

Python采用對(duì)是引用計(jì)數(shù)機(jī)制為主,標(biāo)記-清除和分代收集兩種機(jī)制為輔的策略

引用計(jì)數(shù)機(jī)制

Python里每一個(gè)東西都是對(duì)象,它們的核心就是一個(gè)結(jié)構(gòu)體: PyObject

typedef struct_object {
    int ob_refcnt; // 引用計(jì)數(shù)
    struct_typeobject *ob_type;
} PyObject;

PyObject是每個(gè)對(duì)象必有的內(nèi)容,其中ob_refcnt就是作為引用計(jì)數(shù)。當(dāng)一個(gè)對(duì)象有新的引用時(shí),它的ob_refcnt就會(huì)增加,當(dāng)引用它的對(duì)象被刪除,它的ob_refcnt就會(huì)減少。
當(dāng)引用計(jì)數(shù)為0時(shí),該對(duì)象生命就結(jié)束了。

引用計(jì)數(shù)機(jī)制的優(yōu)點(diǎn):

簡單

實(shí)時(shí)性: 一旦沒有引用,內(nèi)存就直接釋放了。不用像其它機(jī)制等待特定實(shí)際。

處理回收內(nèi)存的時(shí)間分?jǐn)偟搅似綍r(shí)。

引用計(jì)數(shù)機(jī)制的缺點(diǎn):

維護(hù)引用計(jì)數(shù)消耗資源

循環(huán)引用

垃圾回收機(jī)制

Python中的垃圾回收是以引用計(jì)數(shù)為主,分代收集為輔

導(dǎo)致引用計(jì)數(shù)+1的情況
對(duì)象被創(chuàng)建,例如: a = 23
對(duì)象被引用,例如: b = a
對(duì)象被作為參數(shù),傳入到一個(gè)函數(shù)中,例如: func(a)
對(duì)象作為一個(gè)元素,存儲(chǔ)在容器中,例如: list1 = [a,a]

導(dǎo)致引用計(jì)數(shù)-1的情況
對(duì)象的別名被顯式銷毀,例如: del a
對(duì)象的別名被賦予新的對(duì)象,例如: a = 24
一個(gè)對(duì)象離開它的作用域,例如f函數(shù)執(zhí)行完畢時(shí),func函數(shù)中的局部變量(全局變量不會(huì))
對(duì)象所在的容器被銷毀,或從容器中刪除對(duì)象

查看一個(gè)對(duì)象的引用計(jì)數(shù)

import sys
a = "hello world"
sys.getrefcount(a)

可以查看a對(duì)象的引用計(jì)數(shù),但是比正常計(jì)數(shù)大1,因?yàn)檎{(diào)用函數(shù)的時(shí)候傳入a,這會(huì)讓a的引用計(jì)數(shù)+1

循環(huán)引用導(dǎo)致內(nèi)存泄露

引用計(jì)數(shù)的缺陷是循環(huán)引用的問題

import gc

class ClassA():
    def __init__(self):
        print("object born,id:%s"%str(hex(id(self))))

def f2():
    while True:
        c1 = ClassA()
        c2 = ClassA()
        c1.t = c2
        c2.t = c1
        del c1
        del c2

# 把python的gc關(guān)閉
gc.disable()

f2()

執(zhí)行f2(),進(jìn)程占用的內(nèi)存會(huì)不斷增大。

創(chuàng)建了c1, c2后這兩塊內(nèi)存的引用計(jì)數(shù)都是1,執(zhí)行c1.t = c2c2.t = c1后,這兩塊內(nèi)存的引用計(jì)數(shù)變成2.

del c1后,內(nèi)存1的對(duì)象的引用計(jì)數(shù)變?yōu)?,由于不是為0,所以內(nèi)存1的對(duì)象不會(huì)被銷毀,所以內(nèi)存2的對(duì)象的引用數(shù)依然是2,在del c2后,應(yīng)用計(jì)數(shù)也是1,內(nèi)存1的對(duì)象,內(nèi)存2的對(duì)象的引用數(shù)都是1.

雖然他們兩個(gè)對(duì)象都是可以被銷毀的,但是由于循環(huán)引用,導(dǎo)致垃圾回收器不會(huì)回收它們,就導(dǎo)致內(nèi)存泄漏.

垃圾回收

垃圾回收 = 垃圾檢查 + 垃圾回收

有三種情況會(huì)觸發(fā)垃圾回收:

調(diào)用gc.coolect()

當(dāng)gc模塊的計(jì)數(shù)器達(dá)到閥值的時(shí)候

程序退出的時(shí)候

gc模塊

gc模塊作用:解決循環(huán)引用的問題

常用函數(shù):

gc.set_debug(flags)設(shè)置gcdebug日志。一般設(shè)置為gc.DEBUG_LEAK

gc.collect([generation]) 顯式進(jìn)行垃圾回收,可以輸入?yún)?shù),0表示只檢查第一代的對(duì)象,1代表檢查一,二代對(duì)象,2代表檢查一,二,三代的對(duì)象。如果不傳入?yún)?shù),執(zhí)行一個(gè)full collection,也就是等于2,返回不可達(dá)(unreachable objects)對(duì)象的數(shù)目

gc.get_threshold()獲取的gc模塊中自動(dòng)執(zhí)行垃圾回收的頻率

gc.set_threshold(threshold0[, threshold1[, threshold2])設(shè)置自動(dòng)執(zhí)行垃圾回收的頻率

gc.get_count()獲取當(dāng)前自動(dòng)執(zhí)行垃圾回收的計(jì)數(shù)器,返回一個(gè)長度為3的列表

Note:
gc模塊唯一處理不了的是循環(huán)引用的類都有__del__方法,項(xiàng)目中要避免定義__del__方法。

class ClassA():
    pass
    # def __del__(self):
    #     print("object born,id:%s"%str(hex(id(self))))

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/41387.html

相關(guān)文章

發(fā)表評(píng)論

0條評(píng)論

tyheist

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<