day26:靜態方法,類方法和反射

1,包內部不要去嘗試應用使用相對導入,必定不會成功的,他不支持這個機制,包內導入時必定要用絕對導入python

2,複習接口類,抽象類,Python中沒有接口類,有抽象類,抽象類是經過abc模塊中的metaclass = ABCMeta 和@abstractmethod實現的git

3,接口類和抽象類本質是作代碼規範用的,我但願在子類中實現和父類方法名徹底同樣的方法編程

4,兩者區別,在JAVA的角度看是有區別的,JAVA沒有多繼承,因此爲了接口隔離原則,就設計了接口這個概念,支持多繼承;JAVA原本就支持單繼承,因此就有了抽象類。Python中既支持單繼承,也支持多繼承,因此對於接口類和抽象類的區別就不那麼明顯了。甚至在Python中根本沒有接口類,可是Python的擴展模塊中有一個模塊確實實現了接口類的概念,因此不能說根本沒有,只是內置模塊中沒有,沒有內置接口類。網絡

5,多態和鴨子類型,多態---Python天生支持多態,給子類找個爸爸,傳爸爸的參數,Python裏面崇尚鴨子類型,不依賴父類的狀況下,實現兩個類中的同名方法。app

6,封裝 ---私有的,在Python中只要__名字,就把這個名字私有化了,私有化以後,就不能從類的外部直接調用了,能夠私有的有靜態屬性方法,對象的屬性均可以私有化,這種私有化只是從代碼級別作了變形,並無真的約束,變形機制 _類名__方法。在類外用這個調用,在類的外部__名字調用。函數

7,私有屬性spa

class Room:
    def __init__(self,name,length,width):
        self.name = name
        self.__length =length
        self.__width = width
    
    def area(self):
        return self.__length * self.__width

jin = Room('jin',3,5)
print(jin.area())
jin.name = 'lisa'
print(jin.name)

8,get set 方法保護屬性不被修改,私有屬性的查看方法設計

class Room:
    def __init__(self,name,length,width):
        self.__name = name
        self.__length =length
        self.__width = width

    def get_name(self):
        return self.__name

    # 對私有對象的保護
    def set_name(self,new_name):
        if type(new_name) is str and new_name.isdigit() == False:
            self.__name = new_name
        else:
            print('invalid name')

    def area(self):
        return self.__length * self.__width

jin = Room('jin',3,5)
jin.name = '2' # 不是私有的話,能夠隨便改,要想辦法約束一下
print(jin.name)

jin.set_name('lisa')
print(jin.get_name())
# C++ 裏面全部的屬性都設置成私有的,

 9,父類的私有屬性能夠被子類調用嗎?否代碼規範

class Foo:
    __key = '123'  _Foo__key

class Son(Foo):
    print(Foo.__key) #_Son__key # 此句報錯,因爲不能夠調用 
# AttributeError: type object 'Foo' has no attribute '_Son__key

10,總結:會用到私有概念的場景,隱藏起一個屬性,不想讓類的外部調用;我想保護這個屬性,不想讓屬性隨意被改變;我想保護這個屬性不被子類繼承code

11,以前老師欠着的三個內置函數:property,classmethod,staticmethod

12,property,內置裝飾器函數,只在面向對象中使用,可是做爲一個property屬性,函數後面不能傳遞任何參數

from math import pi
class Circle:
    def __init__(self,r):
        self.r = r

    @property
    def perimeter(self):
        return 2 *pi *self.r

    @property
    def area(self):
        return self.r**2*pi

c1 = Circle(5)
# print(c1.area()) # 面積不是動做,是一個屬性才合理,如何假裝成一個屬性呢?
print(c1.area)
print(c1.perimeter)
# c1.area = 70  # 不支持賦值

13,BMI指數,方法假裝的屬性,不被容許修改,怎麼辦?

class Person:
    def __init__(self,name,high,weight):
        self.name = name
        self.high = high
        self.weigh = weight
        # self.bmi = wight / (high **2)  # 這樣寫雖然能夠,可是不規範,操做屬性的方法咱們都是會在方法裏面來寫,各司其職,才更合理

    @property
    def bmi(self):
        return self.weigh/self.high**2

jin = Person('jin',1.75,70)
# print(jin.bmi())
print(jin.bmi)
jin.name = 'tiger'
# jin.bmi = '23'  # 不容許修改,怎麼辦?

14,方法一,name.setter 和 name.deleter

class Person:
    def __init__(self,name):
        self.__name = name

    @property
    def name(self):
        return self.__name + ' nb'

    @name.setter
    def name(self,new_name):  # 雖然是同名函數,可是不會覆蓋
        self.__name = new_name

    @name.deleter
    def name(self):pass  # 裏面不實現的話,是沒有辦法刪除的def self.name

tiger = Person('tiger')
# print(tiger.name())  # tigernb,另外改爲property以後就不能夠這樣覅用了
print(tiger.name)

tiger.name = 'all students' # 沒法修改怎麼辦?再定義一個函數
print(tiger.name)

del tiger.name # 刪除屬性
print(tiger.name) 

# 注意三個函數的名字必須同樣,而且必定要有一個@property方法,才能夠有後面兩個

15,和類屬性的結合

class Goods:
    discount = 0.8
    def __init__(self,name,price):
        self.name = name
        self.__price = price # 私有價格,只有本身知道

    @property
    def price(self):
        return self.__price * Goods.discount

apple = Goods('apple',5)
print(apple.price)

16,staticmethod 靜態的方法 三顆星,classmethod 類方法 四顆星,property 四星半,重要程度,私有屬性,五顆星

17,classmethod ,把一個方法 變成一個類中的方法,這個方法就能夠直接被類調用,不被須要依託於任何對象

class Goods:
    __discount = 0.8
    def __init__(self,name,price):
        self.name = name
        self.__price = price

    @property
    def price(self):
        return self.__price * Goods.__discount

    @classmethod
    def change_discount(cls,new_discount): # 去掉self,咱們不推薦這樣寫,標準寫法,不要寫成其餘的
        cls.__discount = new_discount


# apple = Goods('apple',5)
# print(apple.price)

# 這個折扣修改的動做,咱們如何不本身來完成,而是用一個函數來完成?
# 若是咱們定義成一個對象函數,那麼我必須拿一個對象來進行折扣的修改,可是這個折扣是類屬性,我但願全部的對象都自動修改
# 而不是經過某一個
# apple.change_discount(0.7)
Goods.change_discount(0.9)
# 當這個方法的操做只涉及靜態屬性的時候,就應該使用classmethod

18,staticmethod,若是一個函數自己和類和對象都沒有什麼關係,可是我就想把這個函數寫入到類裏面,想象春面向對象的語言,例如JAVA,C#

class Login:
    def __init__(self,name,password):
        self.name = name
        self.pwd = password

    def login(self):pass

    @staticmethod  # 不須要和類和對象產生任何關係,可是還能夠放在類裏面
    def get_usr_pwd():  # 必須把它扔進類裏面,纔是面向對象
        input('input usrname:')
        input('input password:')


l  = Login('alex','3714')
l.get_usr_pwd() # 靜態方法既能夠被對象來訪問,也能夠用類來訪問
Login.get_usr_pwd()

# 什麼時候使用靜態方法
# 在徹底面向對象的程序中,若是一個函數,既和對象沒有關係,也和類沒有關係,那麼就用staticmethod將這個函數編程一個靜態方法

# 類方法和靜態方法都是類來調用的,那麼對象能夠調用嗎?
# 能夠的,想象對象能夠調用靜態屬性嗎?同樣的道理,可是通常狀況下,推薦用類名來調用
# 類方法,有一個默認參數 cls 表明這個類
# 靜態方法,沒有默認參數,就像函數同樣

19,反射,很是重要,五顆星,把字符串當變量使用

# name = 'lisa'
# 'name'

class Teacher:
    dic = {'show stu info','show teacher info'}

    def show_student(self):
        print('show student')

    def show_teacher(self):
        print('show teacher')

# menu = Teacher.dic
# for k in menu:
#     print(k)

'dic'

# 最後三個內置函數
# hasattr
# getattr
# defattr

ret = getattr(Teacher,'dic')  # 左右對應 Teacher.dic
print(ret)  # {'show stu info', 'show teacher info'}

# python中一切皆是對象,包括類和模塊

20,反射類屬性和類方法

class Teacher:
    dic = {'show stu info','show teacher info'}

    def show_student(self):
        print('show student')

    def show_teacher(self):
        print('show teacher')

    @classmethod
    def func(cls):
        print('hahaha')


ret = getattr(Teacher,'dic')  # 左右對應 Teacher.dic,類.屬性
print(ret)  # {'show stu info', 'show teacher info'}

ret2 = getattr(Teacher,'func')
ret2() # hahaha

if hasattr(Teacher,'func2'):
    ret = getattr(Teacher,'func')
    ret()

if hasattr(Teacher,'dic'):
    ret = getattr(Teacher,'dic')
    print(ret)

21,反射對象方法

# 反射對象函數
lisa = Teacher()
func = getattr(lisa,'show_student')
func()

22,使用實例,有了反射我就不用去一條條判斷了,我只須要一條反射,去掉用相應的方法就好了,反射的妙用

for k in Teacher.dic:
    print(k)

key = input("輸入需求:")
# print(Teacher.dic[key])
# 這個地方好在不須要去判斷if key = 1 怎麼樣,key =2怎麼樣,用反射,程序自動就去調用了
if hasattr(lisa,Teacher.dic[key]):
    func = getattr(lisa,Teacher.dic[key])
    func()

23,反射很是的重要,也許如今只在面向對象這兒還體會不到他的好,可是到了之後網絡編程,文件操做的時候,會用的很是多

24,經過反射能夠對象名獲取對象屬性和普通方法,類名獲取靜態屬性和類方法和靜態方法

25,面向對象思惟導圖和計算器做業先欠着,後補

相關文章
相關標籤/搜索