天天看點

day17面向對象面向對象

面向對象

1.方法

1)對象方法

怎麼定義:直接定義在類中的函數

怎麼調用:通過對象調用

特點:有預設參數self,self在調用的時候不用傳參,系統自動将目前對象傳給self

什麼時候用:如果實作函數的功能需要對象屬性就使用對象方法(對象方法中的self可以用來提供需要所有的對象屬性)

2)類方法

怎麼定義:在類中定義函數前加裝飾器@classmethod

怎麼調用:通過類調用

特點:自帶參數cls,cls在調用的時候也不需要傳參,系統會自動将目前類傳給cls(誰調用就指向誰)

什麼時候用:實作函數功能在不需要對象屬性的時候需要類,就使用類方法

3)靜态方法

怎麼定義:在類型定義函數前加裝飾器@staticmethod

怎麼調用:通過類調用

特點:沒有預設參數

什麼時候用:實作函數功能既不需要類也不需要對象屬性就使用靜态方法

對象方法 類方法 靜态方法
怎麼定義 直接定義在類中的函數 在類中定義函數前加裝飾器@classmethod 在類型定義函數前加裝飾器@staticmethod
怎麼調用 通過對象調用 通過類調用 通過類調用
特點 有預設參數self,self在調用的時候不用傳參,系統自動将目前對象傳給self 自帶參數cls,cls在調用的時候也不需要傳參,系統會自動将目前類傳給cls(誰調用就指向誰) 沒有預設參數
什麼時候用 如果實作函數的功能需要對象屬性就使用對象方法(對象方法中的self可以用來提供需要所有的對象屬性) 實作函數功能在不需要對象屬性的時候需要類,就使用類方法 實作函數功能既不需要類也不需要對象屬性就使用靜态方法
class A:

    # fun1是對象方法
    def fun1(self):
        print('對象方法', self)

    @classmethod
    def fun2(cls):
        print('類方法', cls)

    @classmethod
    def fun3(cls, x):
        print(x)

    @staticmethod
    def fun4():
        print('靜态方法')


print(A)    # <class '__main__.A'>
A.fun2()    # 類方法 <class '__main__.A'>
A.fun3(1)   # 1
A.fun4()    # 靜态方法
           
  • 方法在定義的時候的參數問題:看實作函數的功能除了類中屬性以外需不需要額外的資料,需要幾個
    class Person:
        def __init__(self, name):
            self.name = name
    
        def eat(self, food):
            print(f'{self.name}今天吃了{food}')
               
  • 方法的調用問題:本質上,不管什麼方法都可以用對象和類調用
    a = A()
    a.fun1()
    # A.fun1(100)  # 注意:類可以調用對象方法,但是self就必須自己傳參,失去可以指向目前對象的意義
    
    A.fun2()
    print('====')
    a.fun2()       # 注意:對象可以調用類方法,調用的時候cls還是指向目前類,但是會消耗額外的cpu資源和記憶體資源
               

2.對象屬性的增删改查

class Person:
    def __init__(self, name, tel, age=18, gender='男'):
        self.name = name
        self.age = age
        self.tel = tel
        self.gender = gender

    # __repr__會在目前類的對象被列印的時候自動調用,并且列印結果就是這個函數的傳回值。(傳回值必須是字元串)
    def __repr__(self):
        # return str(self.__dict__)
        return f'<{str(self.__dict__)[1:-1]}>'


p1 = Person('小明', '110')
p2 = Person('小紅', '120', 20, '女')

print(p1)   # print(p1) == print(p1.__repr__())
print(p2)   # <'name': '小紅', 'age': 20, 'tel': '120', 'gender': '女'>
# print(p1.__dict__)
           
  1. 查(擷取對象屬性的值)
    • 對象.屬性
    • getattr(對象,屬性名) / getattr(對象,屬性名,預設值)
    print(p1.name)
    print(getattr(p1, 'name'))
    
    # value = input('請輸入屬性名:')
    # print(getattr(p1, value))
    
    value = 'name'
    # print(p1.value)     # 報錯
    print(getattr(p1, value))
    
    # print(p1.height)    # AttributeError: 'Person' object has no attribute 'height'
    print(getattr(p1, 'height', 170))  # 170
               
  2. 增、改
    • 對象.屬性 = 值
    • setattr(對象, 屬性名, 值)
    print('修改前:', p1)  # 修改前: <'name': '小明', 'age': 18, 'tel': '110', 'gender': '男'>
    p1.age = 20
    print('修改後:', p1)  # 修改後: <'name': '小明', 'age': 20, 'tel': '110', 'gender': '男'>
    
    p1.weight = 60
    print('增加後:', p1)  # 增加後: <'name': '小明', 'age': 20, 'tel': '110', 'gender': '男', 'weight': 60>
    
    setattr(p1, 'height', 170)
    print(p1)   # <'name': '小明', 'age': 20, 'tel': '110', 'gender': '男', 'weight': 60, 'height': 170>
               
    • del 對象.屬性
    • delattr(對象, 屬性名)
    del p1.gender
    print(p1)   # <'name': '小明', 'age': 20, 'tel': '110', 'weight': 60, 'height': 170>
    
    delattr(p1, 'weight')
    print(p1)   # <'name': '小明', 'age': 20, 'tel': '110', 'height': 170>
               

3.内置類的屬性

class Dog:
    """狗類"""
    num = 100

    def __init__(self, name, age=3, color='黃色', gender='公'):
        self.name = name
        self.gender = gender
        self.age = age
        self.color = color

    def show_message(self):
        print(self.name, self.gender, self.color)

    @classmethod
    def show_num(cls):
        print('狗的數量', cls.num)

    @staticmethod
    def info():
        print('狗是人類的朋友!')


dog = Dog('小花')
           
  1. _ _ doc _ _ - 擷取類的說明文檔
    print(Dog.__doc__)
    print(int.__doc__)
               
  2. _ _ class _ _ - 擷取對象的類型(對象屬性),功能和type()函數一樣
    print(dog.__class__)  # <class '__main__.Dog'>
    print(type(dog))      # <class '__main__.Dog'>
               
  3. _ _ name _ _ - 擷取類名(類屬性)
  1. _ _ module _ _ - 擷取類所在的子產品的子產品名(類屬性)
  2. _ _ dict _ _ - 擷取指定類所有的類屬性及其對應的值(以字典的形式傳回) (了解)

    _ _ dict _ _ - 擷取指定對象所有的對象屬性及其對應的值

print(Dog.__dict__)
print(dog.__dict__)  # {'name': '小花', 'gender': '公', 'age': 3, 'color': '黃色'}
           
  1. _ _ base _ _ - 擷取指定類的父類

    _ _ bases _ _ - 擷取指定類的父類們

4.運算符重載

  1. Python中的運算符

    Python中每一個運算符都對應一個固定的魔法方法,每次使用運算符的時候本質就是去調用對應方法。

    某種類型的資料是否支援某種運算符和這個類型中有沒有實作運算符對應的魔法方法有關

  2. 在自己的類中重載指定運算符
    class Student:
        def __init__(self, name, age=18, score=0):
            self.name = name
            self.age = age
            self.score = score
    
        def __repr__(self):
            return f'<{str(self.__dict__)[1:-1]}>'
    
        # ===========運算符重載========
        def __lt__(self, other):
            return self.score > other.score
    
        # self是+前面的資料,other是+後面的資料,傳回值是計算結果
        def __add__(self, other):
            return self.score + other.score
    
    
    stu1 = Student('小明', age=35, score=90)
    stu2 = Student('小紅', age=20, score=80)
    stu3 = Student('湯姆', age=31, score=89)
    print(stu1 != stu2)  # 預設支援比較相等
    
    print(stu1 + stu2)  # 相當于 stu1.__add__(stu2)
    print(stu1)         # <'name': '小明', 'age': 35, 'score': 90>
    
    print(stu1 > stu2)  # True
    
    # 将學生成績從大到小排序
    students = [stu1, stu2, stu3]
    print(sorted(students, key=lambda element:element.score, reverse=True))
    
    students.sort()
    print(students)