IT序号网

Python第六天-面向对象

wyy 2022年04月08日 编程语言 317 0

使用函数模拟定义类

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)

属性查询优先级总结

  1. getattribute(), 无条件调用

  2. 数据描述符:由 ① 触发调用 (若人为的重载了该 getattribute() 方法,可能会导致无法调用描述符)

  3. 实例对象的字典(若与描述符对象同名,会被覆盖)

  4. 类的字典

  5. 非数据描述符

  6. 父类的字典

  7. getattr() 方法


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!