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)

属性查询优先级总结

  1. getattribute(), 无条件调用

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

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

  4. 类的字典

  5. 非数据描述符

  6. 父类的字典

  7. getattr() 方法

posted @ 2020-09-21 22:00  strongmore  阅读(122)  评论(0编辑  收藏  举报