Python第六天-面向对象
使用函数模拟定义类
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() 方法