guxh的python笔记:面向对象

1,面向对象编程思想

类:一类具有相同属性的抽象

      属性(静态属性):实例变量、类变量、私有属性

      方法(动态属性):构造函数、析构函数(默认就有)、函数、私有函数

对象/实例:类经过实例化后,就是对象/实例

封装 encapsulation:隐藏对象的属性和实现细节,仅对外公开接口

继承 inheritance:类派生子类

多态 polymorphism:一个接口,多种实现

举例:

class Foo:  # 类
    typecode = 'd'  # 类变量

    def __init__(self, x, y):  # 构造函数
        self.x = x      # 属性,实例变量
        self._y = y     # 私有属性,实例变量

    def _test(self):    # 私有方法
        return self.x

    def __del__(self):  # 析构函数
        pass

f = Foo(1, 2)   # 类的实例化
print(f)   # 打印类的实例f

2,继承

代码重用

基类不应该被单独实例化

2.1,继承的方法

class Human:
    pass

class Male(Human):
    pass

2.2,子类和父类重名的方法

直接写会覆盖,想保留父类方法可以先执行父类方法再增加子类方法。

class Human:
    def sleep(self):
        print('sleep 1s')

class Male(Human):
    def sleep(self):
        super().sleep()    # 执行父类方法一
        Human.sleep(self)  # 执行父类方法二
        print('sleep 2s')

2.3,子类的构造函数

需要先覆盖父类的构造函数,再继承父类的属性,再增加自己的属性,父类:

class Human:
    def __init__(self, name):
        self.name = name

子类构造函数方法一,多重继承时按指定父类继承:

class Male(Human):
    def __init__(self, name, age):
        Human.__init__(self, name)
        self.age = age

子类构造函数方法二,多重继承时按顺序继承:

class Male(Human):
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age

2.3,多重继承

classA

classB(A)

classC(A)

classD(B, C)

ABCD含有相同方法时:

广度优先:先BC再A

深度优先:先BA再C

python3是广度优先

3,多态

3.1,实现多态

在父类中的一个方法,输入不同子类的对象时,可以实现不同的效果。

父类:

class Human:
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

子类Male:

class Male(Human):

    def hobby(self):
        print('sports')

子类Female:

class Female(Human):

    def hobby(self):
        print('shopping')

不同子类,hobby输出不同,实现了多态:

m = Male('m', 20)
f = Female('f', 20)
m.hobby()  # sports
f.hobby()  # shopping

还可以编写一个入口函数,统一输出不同对象的hobby:

def get_hobby(obj):
    obj.hobby()

get_hobby(m)  # sports
get_hobby(f)  # shopping

3.2,通过抽象基类强制要求子类必须实现方法

如果想要求子类在继承时必须实现hobby方法,可以对父类进行如下改造:

import abc

class Human(abc.ABC):

    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    @abc.abstractmethod 
    def hobby(self):    # 抽象方法无需实现,直接注释或pass即可
        """必须实现hobby"""

4,内置三大类装饰器

4.1,@staticmethod

如果一个方法在类中定义,但没有用到类中的实例属性或者方法,建议加上staticmethod或者classmethod。

staticmethod:本质上就是放在类中的全局函数(可以通过类或实例调用),和类没关系,完全可以放在类的外面。

class Foo:
    def __init__(self, x):
        self.x = x

    @staticmethod
    def run():
        print('hello world')

f = Foo(1)
f.run()     # 输出hello world,通过类的实例调用
Foo.run()   # 输出hello world,通过类调用

 4.2,@classmethod

和staticmethod的区别是可以调用类的属性或方法。

被classmethod装饰的函数第一个参数是类的引用,相当于类的实例中执行type(self),或者self.__class__。

class Foo:
    hw = 'hello world'

    def __init__(self, x):
        self.x = x

    @classmethod
    def run(cls):
        print(cls.hw)

f = Foo(1)
f.run()     # 输出hello world,通过类的实例调用
Foo.run()   # 输出hello world,通过类调用

如果是实例想调用类的属性或方法,可以通过如下方法:

class Foo:
    hw = 'hello world'

    def __init__(self, x):
        self.x = x

    def run(self):
        print(type(self).hw)
        print(self.__class__.hw)

f = Foo(1)
f.run()     # 输出hello world,通过类的实例调用
Foo.run(f)   # 由于没有声明classmethod,无法通过Foo类直接调用run,想调用需把实例f传进去

4.3,@property

详见guxh的python笔记:类的属性

猜你喜欢

转载自www.cnblogs.com/guxh/p/10262621.html