Python第六天-面向物件
阿新 • • 發佈:2020-09-22
使用函式模擬定義類
def Person(name, age): def run(self): print("{name} is running".format(name=self["name"])) def init(): return { "name": name, "age": age, "run": run } return init() # 模擬建立一個物件 lisi = Person("lisi", 24) # 模擬呼叫物件的方法 lisi["run"](lisi)
定義類
class Person():
def __init__(self, name):
self.name = name
def run(self):
print("{} is running".format(self.name))
xiaoming = Person("xiaoming")
xiaoming.run()
使用class 宣告類,預設繼承object類,例項化物件是預設呼叫__init__方法,xiaoming.run() 就類似於 Person.run(xiaoming),self引數就是的當前物件。
物件屬性和類屬性
class Person(object): NAME = "lisi" def __init__(self, name): self.name = name def run(self): print("{} is running".format(self.name)) def of(): return Person(Person.NAME) xiaoming = Person("xiaoming") xiaoming.run() print(Person.NAME) print(Person.__dict__) print(Person.of().__dict__)
name屬性為物件屬性,NAME為類屬性,函式都是類的屬性,當物件呼叫函式時,在當前物件中找不到這個屬性函式,會去類中找,相當於當前作用域和上級作用域的關係。
物件方法,類方法,靜態方法
class Circular():
PI = 3.14
def __init__(self, radius):
self.radius = radius
@property
def perimeter(self):
return 2 * self.PI * self.radius
def calcPerimeter(self):
return 2 * self.PI * self.radius
@staticmethod
def calcArea(radius):
return Circular.PI * radius * radius
@classmethod
def area(cls, radius):
return cls.PI * radius * radius
circular = Circular(2)
print(circular.perimeter)
print(circular.calcPerimeter())
print(Circular.calcArea(2))
print(Circular.area(2))
@property將方法裝飾為一個屬性,@staticmethod表示靜態方法,通過類呼叫,@classmethod表示類方法,也通過類呼叫
類繼承
import abc
class Runnable(metaclass=abc.ABCMeta):
@abc.abstractmethod
def run(self):
pass
class Cat(Runnable):
def run(self):
print("Cat is running...")
class Dog(Runnable):
def run(self):
print("Dog is running...")
cat = Cat()
cat.run()
dog = Dog()
dog.run()
定義一個類似於java中介面的父類,並且將方法定義為抽象方法,這個子類就必須重寫這些方法。
類的內建方法
class Animal():
"""
類的內建方法
"""
"""
訪問屬性首先會呼叫本方法,會檢測__dict__中是否包含屬性 print(obj.item)
"""
def __getattribute__(self, item):
return super().__getattribute__(item)
"""
呼叫__getattribute__方法沒有獲取到時呼叫,print(obj.item)
"""
def __getattr__(self, item):
return "default"
"""
設定物件屬性時呼叫,obj.key=value
"""
def __setattr__(self, key, value):
return super().__setattr__(key, value)
"""
刪除物件屬性時呼叫 del obj.item
"""
def __delattr__(self, item):
return super().__delattr__(item)
"""
以obj[item]方式訪問屬性時被呼叫
"""
def __getitem__(self, item):
return self.__getattribute__(item)
"""
obj[item] = value
"""
def __setitem__(self, key, value):
self.__setattr__(key, value)
"""
del obj[item]
"""
def __delitem__(self, key):
self.__delattr__(key)
"""
str(obj)被呼叫 返回物件的字串形式
"""
def __str__(self):
return "this is Animal"
"""
repr(obj)被呼叫 類似__str__ 控制檯列印
"""
def __repr__(self):
return self.__str__()
"""
len(obj)被呼叫
"""
def __len__(self):
return len(self.__str__())
"""
format(obj)被呼叫
"""
def __format__(self, format_spec):
return "this is Animal"
"""
手動del obj或被gc回收時被呼叫
"""
def __del__(self):
print("del")
pass
"""
obj()被呼叫
"""
def __call__(self, *args, **kwargs):
pass
"""
next(obj)被呼叫,返回迭代器的下一個元素
"""
def __next__(self):
pass
"""
iter(obj)被呼叫,返回一個迭代器物件
"""
def __iter__(self):
return iter([])
class Person():
__slots__ = ["name", "age"]
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("lisi", 23)
p.pwd = "as"
print(p.pwd)
定義了__slots__屬性,物件就沒有__dict__屬性了,就限制了物件的屬性字典,不能增加新的屬性。
描述符
class Desc():
def __set__(self, instance, value):
print("set")
def __get__(self, instance, owner):
print("get")
def __delete__(self, instance):
print("del")
一個類定義了以上3個方法任意一個就是一個描述符,只定義get為非資料描述符,定義了set,del為資料描述符
class TestDesc():
desc = Desc()
test_desc = TestDesc()
test_desc.desc = "a"
print(test_desc.desc)
描述符必須定義為類屬性,當呼叫test_desc.desc = "a"時,實際上會轉換成TestDesc.dict['desc '].get(test_desc, TestDesc)
屬性查詢優先順序總結
-
getattribute(), 無條件呼叫
-
資料描述符:由 ① 觸發呼叫 (若人為的過載了該 getattribute() 方法,可能會導致無法呼叫描述符)
-
例項物件的字典(若與描述符物件同名,會被覆蓋)
-
類的字典
-
非資料描述符
-
父類的字典
-
getattr() 方法