python基礎第八課

一,python中的方法沒有重載
如果定義多個同名方法,則只有最後一個有效。
在其他語言中,可以通過形參列表區分但是python中不可以
測試代碼如下:

class Tx:
    def prints(self):
        print('沒有參數')
    def prints(self,a):
        print('參數爲',a)
t=Tx()
t.prints(1)

結果如下:

參數爲 1

二,方法的動態性
python是動態語言,我們可以動態的爲類添加新的方法,也可以改變已有的方法

測試代碼如下:

class Tips:
    def work(self):
        print('好好學習')
def play(a):
    print('{0}在玩遊戲'.format(a))
def work(a):
    print('{0}在工作'.format(a))
Tips.play=play
Tips.work=work
p=Tips()
p.play() #Tips.play(p)
p.work()

結果如下:

<__main__.Tips object at 0x0000022931185B88>在玩遊戲
<__main__.Tips object at 0x0000022931185B88>在工作

該代碼的關鍵是將play與work看作對象,然後進行操作。相當於在Tips中創建一個類屬性,存放函數的地址。

三,私有屬性與私有方法
要點:(1)兩個下劃線開頭的屬性或方法爲私有的,其他的爲公共有的
(2)類內部可以直接訪問私有屬性和方法
(3)類外部不可以直接訪問私有屬性與方法
(4)在類外部可以通過_類名__私有屬性名來訪問私有屬性
方法在本質上也是屬性,只不過可以用()調用
測試代碼如下:

class Employee:
    __company='yzu'
    def __init__(self,name,age):
        self.name=name
        self.__age=age   #私有屬性
    def __fun(self):      #私有方法
        print('加油')
        print(Employee.__company)   #私有類屬性,注意在類內部引用時,不需要加_類名,但是前面也要加類名
e=Employee('lhy',18)
print(e.name)
#print(e.age)
print(e._Employee__age)
print(dir(e))
#print(e.__fun)
print(e._Employee__fun())
print(Employee._Employee__company)

結果如下:

lhy
18
['_Employee__age', '_Employee__company', '_Employee__fun', '__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__', 'name']
加油
yzu
None
yzu

四,@property修飾器
它可以將一個方法的調用變成屬性調用
測試代碼如下:


class Employee:
    @property
    def salary(self):
        return 10000
e=Employee()
print(e.salary)
#e.salary()錯誤
#e.salary=20000該方法中不可修改

結果如下:

10000

上面代碼無法改變值,下面是改進代碼

class Employee:
    def __init__(self,salary):
        self.__salary=salary
    def get_salary(self):
        return self.__salary
    def set_salary(self,salary):
        if 1000<salary<50000:
            self.__salary=salary
        else:
            print('輸入錯誤')
e=Employee(3000)
print(e.get_salary())
#e.set_salary(4000)
e.set_salary(-2000)
print(e.get_salary())

#改進
class Employee:
    def __init__(self,salary):
        self.__salary=salary
    @property
    def salary(self):
        return self.__salary
    @salary.setter
    def salary(self,salary):
        if 1000<salary<50000:
            self.__salary=salary
        else:
            print('輸入錯誤')
e=Employee(3000)
print(e.salary)
e.salary=-2000
print(e.salary)

結果如下:

3000
輸入錯誤
3000
3000
輸入錯誤
3000

五,面向對象三大特徵
(1)封裝:隱藏對象的屬性和實現細節,只對外提供必要的方法
(2)繼承:繼承讓子類具有父類的特徵,提高代碼重用性
(3)多態:同一種方法調用由於對象不同會產生不同的行爲。

六,繼承
語言格式:class 子類名(父類1,【父類2】。。。)
如果在類體中沒有指定父類,則默認父類爲object類,
object是所有類的父類,裏面定義所有類默認實現的東西,如__new__()
一般來說,構造子類對象一般調用父類的構造函數。
對於父類的私有屬性與私有方法,子類繼承但不可以直接用。
測試代碼如下:

class Person:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def say_age(self):
        print('年齡是{0}'.format(self.__age))


class Student(Person):       #注意縮進,unindent
     def __init__(self,name,age,score):
         Person.__init__(self,name,age)#注意要加self
         self.score=score
s=Student('lhy',18,60)
s.say_age()
print(Student.mro())#打印所屬關係
#如果把age定爲私有屬性
print(s._Person__age)

結果如下:

年齡是18
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
18

七,類成員的繼承與重寫
(1)繼承:子類繼承父類除構造函數外的所有成員
(2)重寫:子類中可以重新定義父類中的方法。
測試代碼如下:

class Person:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def say_age(self):
        print('年齡是{0}'.format(self.__age))


class Student(Person):       #注意縮進,unindent
     def __init__(self,name,age,score):
         Person.__init__(self,name,age)#注意要加self
         self.score=score
     def say_age(self):
         print("{0}的年齡是{1}".format(self.name,self._Person__age))
s=Student('lhy',18,60)
s.say_age() #覆蓋了父類的方法

結果爲:

lhy的年齡是18

八,object根類
測試代碼如下:

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

    def say_age(self):
        print('年齡是{0}'.format(self.__age))
print(dir(object))
s=Person('lhy',18)
print(dir(s))
s1=s.name
s2=s._Person__age
s3=s.say_age
print(type(s1))
print(type(s2))
print(type(s3))#方法也是屬性,只不過是method屬性,可以用()調用

結果如下:

['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
['_Person__age', '__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__', 'name', 'say_age']
<class 'str'>
<class 'int'>
<class 'method'>

九,__str__方法
該方法用來返回一個對象的描述,用print()方法時,會使用該方法
測試代碼如下:

class Person:
    def __init__(self,name):
        self.name=name
s=Person('lhy')
print(s)
#若使用str
class Person1:
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return '修改了' #不用return會報錯
s=Person1('lhy')
print(s)

結果如下:

<__main__.Person object at 0x0000027D6CD2AD08>
修改了

十,多重繼承與特殊屬性
多重繼承會將類的整體結構搞得複雜,應該避免使用
測試代碼如下:

class A:
    def a(self):
        print('a')
    def say(self):
        print('aaa')
class B:
    def b(self):
        print('b')
    def say(self):
        print('bbb')
class C(A,B):
    pass
c=C()
c.a()
c.b()
c.say()#由於繼承時候A在前面
print(C.mro())#c不可以
print(c.__dict__)
print(c.__class__)
print(C.__bases__)
print(C.__base__)
print(C.__mro__)
print(A.__subclasses__())

結果如下:

a
b
aaa
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
{}
<class '__main__.C'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>]

十一,super()獲取父類定義
在子類中,如果想獲得父類方法時,可以通過super()來實現
super()代表父類的定義,不是父類的對象
測試代碼如下:

class A:
    def a(self):
        print(self)
class B(A):
    def say(self):
        #A.a(self)
        super().a()#與上語句相似
        print(self)
#b=B()
#b.say()
B().say()

結果爲:

<__main__.B object at 0x0000024E8A450548>
<__main__.B object at 0x0000024E8A450548>

十二,多態
多態是由於對象不同而產生不同行爲
要點:(1)只有方法有多態,屬性沒有多態
(2)多態必須存在兩個必要條件:繼承與方法重寫
測試代碼如下:

class Man:
    def eat(self):
        print('喫飯行爲')

class Chinese(Man):
    def eat(self):
        print('用筷子喫')

class English(Man):
    def eat(self):
        print('用刀叉喫')


class Indian(Man):
    def eat(self):
        print('用右手喫')

def maneat(m):
    if isinstance(m,Man):
        m.eat()
    else:
        print('不能喫飯')

maneat(Chinese())
maneat(English())
maneat(Indian)
maneat(Man())

結果爲:

用筷子喫
用刀叉喫
不能喫飯
喫飯行爲

十三,特殊方法與運算符重載
測試如下:

class Person:
    def __init__(self,name):
        self.name=name
    def __add__(self, other):
        if isinstance(other,Person):#檢測是不是Person類
            return "{0}__{1}".format(self.name,other.name)#這裏的other其實是一個Person對象
        else:
            return "不能打印"
    def __mul__(self, other):
        if isinstance(other,int):
            return self.name*3
        else:
            return "不能打印"
p1=Person('lhy')
p2=Person('zm')
c=p1+p2
print(c)
d=p1*3
print(d)

結果爲:

lhy__zm
lhylhylhy


在這裏插入圖片描述
十四,對象的淺拷貝與深拷貝
測試代碼如下:

import copy
class Phone:
    def __init__(self,cpu,screen):
        self.cpu=cpu
        self.screen=screen
class Cpu:
    pass
class Screen:
    pass

#測試變量賦值
c=Cpu()
c2=c
print(c)
print(c2)
s=Screen()
print('測試淺拷貝')
p=Phone(c,s)#Phone(1,2)?
p1=copy.copy(p)
print(p,p.cpu,p.screen)
print(p1,p1.cpu,p1.screen)
print('測試深拷貝')
p2=copy.deepcopy(p)
print(p,p.cpu,p.screen)
print(p2,p2.cpu,p2.screen)

結果如下:

<__main__.Cpu object at 0x000001D7AFC3C748>
<__main__.Cpu object at 0x000001D7AFC3C748>
測試淺拷貝
<__main__.Phone object at 0x000001D7B0B99DC8> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
<__main__.Phone object at 0x000001D7AFC48288> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
測試深拷貝
<__main__.Phone object at 0x000001D7B0B99DC8> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
<__main__.Phone object at 0x000001D7B0C23248> <__main__.Cpu object at 0x000001D7B0C23BC8> <__main__.Screen object at 0x000001D7B0C23C48>

十五,組合
is-a關係用繼承
has-a關係用組合
測試代碼如下:

class A1:
    def a1(self):
        print('aaa')
class B1(A1):
    pass
B1().a1()

#組合
class A2:
    def a2(self):
        print('bbb')
class B2:
    def __init__(self,a):
        self.a=a
B2(A2()).a.a2()#這裏B2中包含A2,然後將A2()的對象,傳入B2中,用來創建a,所以a.a2()可以調用

結果如下:

aaa
bbb

十六,工廠模式實現

class CarFactory:
    def create_car(self,brand):
        if brand=='奔馳':
            return BC()
        elif brand=='比亞迪':
            return BYD()
        elif brand=='法拉利':
            return FLL()
class BC:
    pass
class BYD:
    pass
class FLL:
    pass

factory=CarFactory()
c1=factory.create_car('奔馳')
c2=factory.create_car(('比亞迪'))

十七,單例模式實現

class Dan:
    __obj=None
    init_flag=True
    def __new__(cls, *args, **kwargs):
        if cls.__obj==None:#忘加cls
            cls.__obj=object.__new__(cls)
        return cls.__obj
    def __init__(self):
        if Dan.init_flag==True:#忘加Dan
            Dan.init_flag=False
            print('執行了')

d1=Dan()
d2=Dan()
print(d1)
print(d2)

結果如下:

執行了
<__main__.Dan object at 0x0000021EB37C4B88>
<__main__.Dan object at 0x0000021EB37C4B88>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章