day27:反射和雙下方法

1,python

# 面向對象的三大特性:繼承,多態和封裝
# 繼承:
    # 單繼承: ****
        #  父類(超類,基類)
        #  子類(派生類)  派生方法和派生屬性
        #  子類的對象在調用方法和屬性:先用本身的,本身沒有,採用父類的
    # 多繼承:(面試)
        # 不會超過三個父類,不要超過三層 ***
        # 若是子類本身有用本身的,若是沒有就用離子類最近的那個父類的
        # 抽象類和接口類 **
        # 經典類和新式類 繼承規則不一樣,深度優先和廣度優先 ***** (面試)
    # super 只有在python3中使用 mro ****
        # super 是根據mro 廣度優先順序找上一個類
# 多態:(面試)
    # 多態和鴨子類型

# 封裝:***(面試)
    # 私有的
    #__名字
    # 只能在類的內部調用,子類都沒法繼承

# 三個裝飾器
    # @property **** 規範 面試 # @name.setter
    # @staticmethod ***
    # @classmethod  ***** 當一個方法使用了類的靜態變量時,就給這個方法加上@classmethod裝飾器,默認傳cls參數
View Code

2,面試

class Goods():
    __discount = 0.8
    @classmethod
    def change_discount(cls):
        cls.__discount = 0.5

Goods.change_discount()

3,組合:表達的是什麼有什麼的關係 五顆星,一個類的屬性是另一個類的對象安全

4,面向對象的進階app

# isinstance() 和 issubclass()  ***
# 反射 ****** 很是很是的重要,高級的設置,JAVA裏面也有反射,會讓程序變得很簡潔,任何地方均可以用,模塊函數均可以
#     setattr()
#     delattr()
#     getattr()
#     hasattr()
# __str__ 和__repr__  **  全部雙下方法,知道有這麼個方法就行,主要是不少人用不太好這些雙下方法
# __del__
# item系列
#     __getitem__
#     __setitem__
#     __delitem__

5,isinstance 檢查一個obj是不是一個類的對象ide

class Foo():pass
class Foo1():pass
obj = Foo()
print(isinstance(obj,Foo))
print(isinstance(obj,Foo1))

6,issubclass(sub,super) 檢查sub類是不是super類的派生類函數

class A():pass
class B(A):pass
print(issubclass(B,A))

7,反射,很是很是重要的知識點,反射是用字符串類型的名字去操做變量,和eval有點相似spa

8,反射對象的屬性code

name = 1
eval('print(name)')
# eval會有很大的安全隱患,由於你不知道你執行的代碼是什麼來自哪裏,除非寫死了,否則有很大的安全隱患
# 可是反射就不會有安全問題,他不是真的拿到了一段python代碼,他是操做內存中已經存在的變量

# 第一種:反射對象中的屬性和方法
class A:
    def func(self):
        print('in func')

a = A()
a.name = 'Alex'

# 反射對象的屬性
ret = getattr(a,'name')  # 經過變量名的字符串形式取到值
print(ret)
print(a.__dict__)

變量名 = input(">>>")
print(getattr(a,變量名))
print(a.__dict__[變量名]) # 至關於這樣,可是咱們通常不這麼用

9,反射對象的方法對象

class A:
    def func(self):
        print('in func')

ret = getattr(a,'func')
ret()

10,反射類的屬性,方法和靜態方法blog

class A:
    price = 20
    def __init__(self,name):
        self.name = name
    def func(self):
        print('in func')

    @classmethod
    def func2(cls):
        print('classmethod')

    @staticmethod
    def func3():
        print('staticmethod')

a = A('lisa')
# 反射對象的屬性
if hasattr(a,'name'):
    ret = getattr(a,'name')
    print(ret)
# 反射對象的方法
if hasattr(a,'func'):
    ret = getattr(a,'func')
    ret()

# 反射類的屬性
if hasattr(A,'price'):
    ret = getattr(A,'price')
    print(ret)

# 反射類的方法
if hasattr(A,'func2'):
    ret = getattr(A,'func2')
    ret()

# 反射靜態的方法
if hasattr(A,'func3'):
    ret = getattr(A,'func3')
    ret()

11,反射模塊的屬性和方法

# 模塊my的代碼
day = "monday"
def func():print('func in module my.py')
import my
# 反射模塊的屬性和方法

print(getattr(my,'day'))
print(getattr(my,'func'))

12,反射本身模塊中的變量,另外本身模塊的函數也是能夠的

import sys
year = 2019
print(sys.modules['__main__'].year)
print(sys.modules['my'])

def qqxing():print('qqxing')

# 反射本身模塊中的變量
ret = getattr(sys.modules['__main__'],'qqxing') # 這樣寫實際上是有坑的,由於若是我不是在這個模塊開始運行的,他就不叫__main__了
ret()
print(getattr(sys.modules[__name__],變量名)) # 這樣就能夠了

13,應用time模塊的一個小實例,要反射的函數有參數如何處理?下面的例子給出瞭解答

import time
print(time.strftime('%Y-%m-%d %H:%M:%S'))
print(getattr(time,'strftime')('%Y-%m-%d %H:%M:%S'))

14,一個模塊中的類能不能反射獲得

import my
print(getattr(my,"C")) # 拿到類
print(getattr(my,"C")()) # 實例化

15,總結:什麼.什麼的形式均可以用反射來獲得,目前咱們沒有用到太多應用他的場景,可是後面用到他的地方很是多

16,getattr和hasattr 是一對兒,夫妻檔要一塊兒用

17,setattr,delattr幾乎不會用到的,不佔用星,用的很是少

class A:
    pass

a = A()
setattr(A,'name','nezha')
setattr(a,'name','alex')

print(A.name)
print(a.name)

delattr(a,'name') # 刪掉對象的會用類的name

print(A.name)
print(a.name) 

18,類裏面內置的雙下方法,__str__ 和__repr__  之前有講過str()和repr()

class A(object):pass
    # def __str__(self):  # 只要是str方法,必定要返回一個字符串
    #     return 'str方法'

a = A()
print(str(a))
若是類裏面的str方法沒有實現,那麼會去調用object類裏面的str方法,返回類的字符串
object裏面有一個__str__,一旦被調用,就返回調用這個方法的對象的內存地址
運行結果:
<__main__.A object at 0x1072d6320>
class A(object):
    def __str__(self):  # 只要是str方法,必定要返回一個字符串
        return 'str方法'
# 本身實現了str方法會用本身的
a = A()
print(str(a))  # 會自動調用類裏面的雙下str方法
運行結果:
str方法

19,str print str %s

class A(object):
    def __str__(self):  # 本身寫會定義一個比較人性化的結果
        return "A's object"

a = A()
print(str(a))
print(a)  # 默認打印一個對象,就是打印出這個對象的地址,調用a.__str__
# 這個不涉及原理或者什麼,只是python的一種規定
l = [1,2,3,4,5] # 實例化了一個列表類的對象
print(l) # 爲什麼打印l就會顯示出裏面的每個元素,這就是他作了處理
# [1, 2, 3, 4, 5]
class A(object):
    def __str__(self):  # 本身寫會定義一個比較人性化的結果
        return "A's object"

a = A()
print('%s:%s'%(A,a)) %s實際上走的也是雙下str方法
運行結果:
<class '__main__.A'>:A's object

20,__repr__,調用repr和%r方法會自動調用類裏面的雙下repr方法

class Teacher(object):
    def __init__(self,name,salary):
        self.name = name
        self.salary = salary

    def __str__(self):  # 本身寫會定義一個比較人性化的結果, 若是不返回str會報錯的
        return "A's object"


    def __repr__(self):
        return str(self.__dict__)

lisa = Teacher('lisa',100)
print(lisa)
print(repr(lisa))

運行結果:
A's object
{'name': 'lisa', 'salary': 100}

21,總結一下

# 本身沒有定製雙下repr方法,那麼會調用父類的repr方法,輸出對象的內存地址,
# repr方法是str方法的備胎,本身沒有定製str方法,那麼會找repr方法,若是也沒有repr方法,那麼會調用父類的str方法。

22,repr是 str的備胎,str不能作repr的備胎

23,雙下len方法,這些雙下方法又稱爲魔法方法,是調用其餘的自動來觸發的

class A:
    def __len__(self):
        return 100  # 返回值必須是整數,小數也不行

a = A()
print(len(a))

23,__len__,這個方法必須實現了,才能夠在下面調用,object類並無定義全部的雙下__len__方法,不必定全部的內置方法都被object收錄了,比方說數字。有一些模塊,好比說時間,不具有len,也沒有意義,因此只能是全部的類都有的,會被object收錄。定製對象的長度

class Classes:
    def __init__(self,name):
        self.name = name
        self.student = []

    def __len__(self):
        return len(self.student)

s9 = Classes('python')
s9.student.append('lisa')
s9.student.append('lucy')
print(len(s9))  # 2

24,__del__雙下del方法,析構方法,del 既執行了方法,又刪除了變量,析構函數,在刪除一個對象以前,在作一些收尾工做

class A:pass
    # def __del__(self):
    #     print('執行我啦!')

a = A()
del a   # 會自動調用雙下del方法
print(a) # 提示出錯,NameError: name 'a' is not defined
# 須要注意的是a 雙下del 即便咱們不定製,那麼調用的時候也會自動去調用父類的雙下del刪除

25,del 被刪除的狀況,引用計數,達到零了會被刪除,這是第一種狀況,第二種狀況,

26,雙下__call__方法

class A:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    # def __call__(self):
    #     print('執行我啦lala')

    def __call__(self, *args, **kwargs):
        for k in self.__dict__:
            print(k,end=' ')

a = A('lisa',22)
a()  # TypeError: 'A' object is not callable ,不實現call方法會報出這個錯誤
A('lisa',22)() # 見到這樣的不要不認識,實際上就是調用雙下call方法
相關文章
相關標籤/搜索