Python

一种设计思想

面向对象

  1. 面向对象
    • 对象
    • 属性
    • 方法
  2. 构成
    • 封装(私有化)
    • 继承
    • 多态(多父类)
  3. class
    • 定义类
  4. 类的方法(函数)
    • 普通
    • 静态
    • 魔术方法

代码示例:

class Foo:  # 默认继承父类(object),可省略空括号
    bar = 'bar'

object1 = Foo()  # 创建对象object1
print(object1.bar)  # bar

object2 = Foo()  # 创建对象object2
object2.bar = 'foo'  # 修改类作用于对象的属性(此修改仅作用于对象,类属性不会受影响)
print(object2.bar)  # foo(调用顺序:对象属性 > 类属性)

Foo.bar = 'bar'  # 修改类属性

普通方法

代码示例:

# 示例01:
class Foo:
    def bar(self):  # self相当于this,当前类的对象(self与object1的内存地址一样,也可以通过self调用函数本身递归)
        print(self)

object1 = Foo()
object1.bar()  # <__main__.Foo object at 0x000002EB78163EE0>

# 示例02(公共属性:类中函数都可以通过self来使用属性):
class Foo:
    def __init__(self,name):  # 只要创建对象,__init__函数就会执行(再将内存地址赋值给对象)
        print('__init__',end = ' ')
        self.name = name

    def bar(self):
        print(self.name)

object1 = Foo('HQSY')  # 相当于执行__init__函数的内容
object1.bar()  # __init__ HQSY

类方法

  1. @classmethod
    • 定义类方法
  2. 特点(不依赖于对象,在创建对象之前就可以使用)
    • 定义需要依赖装饰器(@classmethod)
    • 类方法中的参数不是对象,而是类
    • 类方法中只可以使用类属性
    • 类方法可以直接使用(类名.类方法)来访问
    • 类方法中不可以使用普通方法中的属性

代码示例:

class Foo:
    bar = 'bar'
    @classmethod
    def app(self):
        print(self.bar)

Foo.app()  # bar

# 私有化:
class Foo:
    __bar = 'bar'

    def app(self):
        self.__bar = 'app'
        print(self.__bar)

object1 = Foo()
object1.app()  # app
print(object1.__bar)  # 报错
print(Foo.__bar)  # 报错

静态方法

  1. 特点
    • 需要装饰器(@staticmethod)
    • 定义函数时可不带参数
    • 只能访问类属性和方法,对象是无法访问的
    • 加载时机同类方法一起同时加载

代码示例:

class Foo:
    bar = 'bar'

    @staticmethod
    def app():
        print(Foo.bar)

Foo.app()  # bar

'''
类、静态方法总结:

1. 不相同
    · 装饰器不同
    · 类方法是有参数的,而静态方法无参数
2. 相同
    · 只能访问类的属性和方法,对象是无法访问的
    · 都可以通过类名调用访问
    · 都可以在创建对象之前使用,因为都是不依赖对象的
3. 普通方法与类、静态方法的区别
    · 没有装饰器
    · 普通方法永远依赖于对象,因为每个普通方法都有一个必要参数(self)来存放对象的内存地址
    · 只有创建了对象才可以调用普通方法,否则无法调用
'''

魔术方法

代码示例:

'''
1. __init__
    · 初始化对象属性(执行时机:创建对象)
2. __new__
    · 实例化(执行时机:创建对象)
3. __del__
    · 析构(执行时机:手动删除,系统回收)
4. __call__
    · 调用对象(执行时机:对象名被当作函数名调用)
5. __str__
    · 方法中的return会返出值(执行时机:打印对象名)
'''

# __new__:
'''
逻辑:对象传的值先给了__new__,再随着return返给了__init__(整个过程地址从头到尾都是一个"新地址"),最后再把"加工"后的地址赋给了对象
'''
class Foo:
    def __init__(self):
        print('__init__')

    def __new__(cls):  # 按照规范形参名称填写cls
        print('__new__')
        return object.__new__(cls)  # return返出创建的新地址给了__init__,cls:新地址(如果不return,那么bar接收的值为空)

bar = Foo()
'''
__new__
__init__
'''

# __call__:
'''
逻辑:执行时机满足时,就会执行__call__函数体
'''
class Foo:
    def __call__(self,bar):
        print(bar)

object01 = Foo()
object01('bar') # bar

# __del__:
'''
逻辑:当一块空间没有了任何引用时,就会执行__del__函数体(当执行完全部代码时,系统会先删除全部引用,再回收全部空间)
'''
class Foo:
    def __init__(self,bar):
        self.bar = bar

    def __del__(self):
        print(self.bar)

object01 = Foo('bar')
object02 = object01
object03 = object01
del object01
print('foo')
del object02,object03
'''
foo
bar
'''

# __str__:
'''
逻辑:打印对象时就会执行__str__函数体,返出的值给了对象(使类的信息更加完整)
'''
class Foo:
    def __str__(self):
        return 'bar'  # 必须是字符串

object01 = Foo()
print(object01)  # bar

# 引用补充:
class Foo:
    def __init__(self,bar):
        self.bar = bar

object01 = Foo('bar')
object02 = object01
object03 = object01
object01.bar = 'foo'  # 在原有的地址空间做修改
print(object02.bar,object03.bar)  # foo foo

P01 = 'foo'
P02 = P01
P01 = 'bar'  # 直接改变地址
print(P02)  # foo

# 类中的方法相互调用补充:
class Foo:
    def a(self):
        pass

    def b(self):
        self.a()

私有化

  1. 概念
    • 不允许外界对象修改类中私有化类对象属性的值,只能从类里面修改
    • 私有化属性、定义公有的set方法(赋值)和get方法(取值)
  2. 特点
    • 隐藏属性不被外界直接随意更改
    • 修改时必须通过set函数体的逻辑处理才可以做修改
    • 如果想获取具体的某一个属性,可通过get函数体访问对应的属性
    • 子类继承不了父类的私有化属性
  3. 符号
    • __

代码示例:

class Foo:
    def __init__(self, a):
        self.__a = a  # 不允许直接从外界改变

    def mySet(self, b):  # 允许从外界改变的方法
        self.__a = b

    def myGet(self):
        return self.__a  # 允许从外界查看属性的方法


object01 = Foo('foo')
print(object01.myGet())
object01.mySet('bar')
print(object01.myGet())
'''
foo
bar
'''

# 强制访问私有化的属性:
'''
1. __dict__
    · 可以理解为dir()的子集(返回值:dict)
    · 之所以访问不了私有化属性是因为系统底层进行了重命名(伪私有化)
'''
class Foo:
    __bar = 'foo'

print(Foo.__dict__)
print(Foo._Foo__bar)
'''
{'__module__': '__main__', '_Foo__bar': 'foo', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
foo
'''

dir

查看类中所有属性与函数(返回值:list)

代码示例:

# 包括系统底层内置的东西
class Foo:
    bar = 'foo'
    def a(self):
        pass

print(dir(Foo))  # ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'bar']

# 特殊私有化处理:
class Foo:
    def __init__(self, bar):
        self.__bar = bar

    @property  # get(可单独使用)
    def a(self):
        return self.__bar

    @a.setter  # set(必须与@property配合使用)
    def a(self, bar):
        if bar == 'foo':
            self.__bar = bar


object01 = Foo('bar')
object01.a = 'foo'  # 给私有化的属性赋值
print(object01.a)  # foo

关联关系

  1. has-a
    • 一个类中使用了另一种自定义类型
  2. 自定义类型
    • 算是自定义类,都可以将其当成一种数据类型

代码示例:

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

    def __str__(self):  # 如果没有__str__方法,那么输出的将是自定义类型对象的内存地址
        return self.bar


class Bar:
    def __init__(self, bar):
        self.bar = bar

    def __str__(self):
        return str(self.bar)  # 不转str会报错,因为是自定义类型


# 自定义类型与系统类型是根本上的区别
object01 = Foo('bar')  # 实参为自定义类型,object01为自定义类型的对象
object02 = Bar(object01)  # 把自定义类型的对象当作实参传入到类中(转换为str时会自动调用Foo类中的__str__方法)
print(object02)

继承关系

  1. 作用
    • 代码复用
  2. is-a
    • 一个类中继承了父类的属性或动作

代码示例:

class Foo:  # 父类
    def __init__(self):
        self.a = 'bar'

    def b(self):
        print(self.a)


class Bar(Foo):  # 子类继承父类
    pass


object01 = Bar()
object01.b()  # bar

super

指向父类的内存地址

代码示例:

'''
1. super().__init__()
    · 等同于 super(子类名, self).__init__()
    · 只不过源式子多了一个类型判断(对象是不是类型造出来的)

class Bar(Foo):
    def __init__(self):
        Foo.__init__(self)
'''
class Foo:  # 父类
    def __init__(self):
        self.a = 'foo'

    def b(self):
        print(self.a)


class Bar(Foo):  # 子类继承父类
    def __init__(self):
        print('bar')
        super().__init__()  # 调用父类的__init__方法
        super().b()  # 调用父类的b方法


object01 = Bar()
object01.b()
'''
bar
foo
foo
'''

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

    def b(self):
        print('foo')


class Bar(Foo):
    def __init__(self, c):
        print('bar')
        super().__init__(c)  # 传给父类,且因为继承了父类,这块空间也同等地有了'self.a'属性


class Hoo(Foo):
    pass


object01 = Bar('kurosaki')
object01.b()
object02 = Hoo('shigure')  # 子类无__init__时默认传给父类,且因为继承了父类,这块空间也同等地有了'self.a'属性
object02.b()
'''
bar
foo
foo
'''

# 如果子类与父类有同名的方法,则优先级为子类 > 父类(重构)
class Foo:
    def a(self):
        return 'foo'

class Bar(Foo):
    def a(self):
        return 'bar'

object01 = Bar()
bar = object01.a()
print(bar)  # bar

inspect

  1. 概念
    • Python允许多重继承(如果类中有相同名称的方法,则依照搜索顺序)
  2. getmro
    • 显示多重继承搜索顺序(返回值:tuple)

代码示例:

import inspect

class Foo:
    def a(self):
        print('foo')


class A(Foo):
    def a(self):
        print('a')


class B(Foo):
    def a(self):
        print('b')


class C(A, B):
    pass


object01 = C()
object01.a()  # a
print(inspect.getmro(C))  # (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Foo'>, <class 'object'>)

# __mer__:显示多重继承搜索顺序(返回值:tuple)
print(C.__mro__)  # (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Foo'>, <class 'object'>)

# 经典多重继承
class A:
    def foo(self):
        print('A foo')

    def bar(self):
        print('A bar')


class B:
    def foo(self):
        print('B foo')


class C(A, B):
    pass


class D(A, B):
    def bar(self):
        print('D bar')


class F(C, D):
    pass


object01 = F()
object01.foo()
object01.bar()
'''
A foo
D bar
'''

多态

代码示例:

class A:
    def __init__(self, a):
        self.a = a

    def foo(self, args):  # Python形参可以接收不同父类的子类的自定义类型的实参
        if isinstance(args, B):  # 判断是否继承或属于类B
            print('foo')
        else:
            print('bar')


class B:
    def __init__(self, b):
        self.b = b


class C(B):
    def bar(self):
        print('C')


class D:
    def how(self):
        print('D')


object01 = C('object01')
object02 = A('object02')
object02.foo(object01)
object03 = D()
object02.foo(object03)
object04 = B('object04')
object02.foo(object04)
'''
foo
bar
foo
'''

单例模式

作用:节约内存空间(因为每次创建对象时都会产生新的内存空间)

代码示例:

'''
1. 每次创建对象时都会先访问类中的__new__方法,如果类中没有,则去父类object中寻找__new__方法
2. 如果类中有__init__,return时会先返给__init__方法,再返给创建的类对象
'''
class Foo:
    __bar = None  # 单例的地址就存放在__bar变量中,之所以私有化是因为不被外界访问与修改

    def __new__(cls):  # cls指的是当前的类(重写父类object的__new__方法,使得创建对象时不产生新的内存地址)
        if cls.__bar is None:
            cls.__bar = object.__new__(cls)  # 本质上就是调用父类产生一个内存地址再返出去,则当多次创建类对象时走的else分支
            return cls.__bar
        else:
            return cls.__bar  # 返出相同的内存地址给类对象


object01 = Foo()
object02 = Foo()
print(object01)
print(object02)
'''
<__main__.Foo object at 0x0000022488E2DFA0>
<__main__.Foo object at 0x0000022488E2DFA0>
'''