python-从入门到就业-面向对象

python面向对象

内置方法

__call__方法

  • 使得对象具备当作函数来调用的能力
class Person:
    def __call__(self, *args, **kwargs):
        print("xxx", args, kwargs)
    pass

p = Person()
p("hello")#xxx ('hello',) {}
class PenFactory:
    def __init__(self, p_type):
        self.p_type = p_type

    def __call__(self, p_color):
        print("类型:%s,  颜色%s" % (self.p_type, p_color))

gangbi = PenFactory("钢笔")
gangbi("绿色")
gangbi("红色")
'''
类型:钢笔,  颜色绿色
类型:钢笔,  颜色红色
'''

索引操作

  • 对一个实例对象进行索引操作
class Person:
    def __init__(self):
        self.cache = {}
    def __setitem__(self, key, value):
        #print("setitem", key, value)
        self.cache[key] = value
    def __getitem__(self, item):
        #print("getitem", item)
        return self.cache[item]
    def __delitem__(self, key):
        #print("delitem", key)
        del self.cache[key]
#想对对象进行类似字典的操作需要在里面定义内置的item函数
p = Person()
p["name"] = "niko" #setitem name niko
print(p.__dict__)#{'cache': {'name': 'niko'}}
print(p["name"])#niko
del p["name"]
print(p.__dict__)#{'cache': {}}

切片操作

class Person:
    def __init__(self):
        self.items = [1, 2, 3, 4]
    def __setitem__(self, key, value):
        print(key.start, key.stop, key.step, value)
        self.items[key] = value
    def __getitem__(self, item):
        print("getitem", item)
p = Person()
p[0 : 4 : 2] = ["a", "b"]
print(p.__dict__)
p[0 : 2]
'''
0 4 2 ['a', 'b']
{'items': ['a', 2, 'b', 4]}
getitem slice(0, 2, None)
'''

比较操作

  • 对于反向操作的比较运算符,如果只定义了其中一种方法,但是使用的是另外一种比较运算,系统会采用调换参数的方式进行方法调用。但是,不支持叠加操作。
import functools
@functools.total_ordering #会自动补全其他方式
class Person:
    def __init__(self, age, height):
        self.age = age
        self.height = height
    def __lt__(self, other):
        print(self.age, other.age)#采用调换参数实现
        return self.age < other.age#p1自动映射为self,p2映射为other
    def __eq__(self, other):
        return self.age == other.age

p1 = Person(18, 160)
p2 = Person(19, 240)
print(p1 < p2)#True
print(p1 * p2)#False
print(p1 == p2)#False
print(Person.__dict__)#{ '__lt__': <function Person.__lt__ at 0x0000022E1DBB4F70*, '__eq__': <function Person.__eq__ at 0x0000022E1DBB4EE0*}
print(Person.__dict__)
#: <function Person.__init__ at 0x0000022DD1554F70*, '__lt__': <function Person.__lt__ at 0x0000022DD1554EE0*, '__eq__': <function Person.__eq__ at 0x0000022DD155D040*,  '__gt__': <function _gt_from_lt at 0x0000022DD14D7AF0*, '__le__': <function _le_from_lt at 0x0000022DD14D7B80*, '__ge__': <function _ge_from_lt at 0x0000022DD14D7C10*}
print(p1 <= p2)#True 组合了小于和等于

上下文环境的布尔值

class Person:
    def __bool__(self):#代表了该类型对象的真假
        return False
    pass

p = Person()
print(bool(p))#False

遍历操作

  • 怎样可以使得我们自己创建的对象可以使用for in进行遍历?①实现__getitem__方法 ②实现__iter__方法
  • 怎样可以使得我们自己创建的对象可以使用next进行访问?
class Person:
    def __init__(self):
        self.result = 1
    def __getitem__(self, item):#要自行设置终止条件,不要死循环
        print("getitem")
        self.result += 1
        if self.result *= 6:
            raise StopIteration("停止遍历")
        return self.result
    def __iter__(self):#方式2优先级高于getitem
    #要返回迭代器,有next方法的对象才是迭代器
        return self
    def __next__(self):
        self.result += 1
        if self.result *= 6:
            raise StopIteration("停止遍历")
        return self.result
p = Person()
for i in p:
    print(i)
'''
2
3
4
5
'''
next访问对象
class Person:
    def __init__(self):
        self.result = 1
    def __next__(self):
        self.result += 1
        if self.result *= 6:
            raise StopIteration("停止遍历")
        return self.result
p = Person()
print(next(p))
'''
2
'''
  • 对象如为迭代器必须要实现iter和next俩个方法
class Person:
    def __init__(self):
        self.age = 1
    def __iter__(self):
        self.age = 1
        return self

    def  __next__(self):
        self.age += 1
        if self.age *= 3:
            raise StopIteration("Stop")

        return self.age

p = Person()
import collections
print(isinstance(p, collections.Iterator))#True
for i in p:
    print(i)
for i in p:
    print(i)
'''
2
2
'''
  • 迭代器只可以遍历一次,想多次使用需要在iter中进行回退操作,也就是初始化
  • getitem即使可以使用for in访问但是并不是可迭代对象
  • Iterable必须是要有iter方法
  • 可迭代对象一定可for in访问,反之不成立
class Person:
    def __init__(self):
        self.age = 1

    def __iter__(self):
        self.age = 1
        return self
    def __call__(self, *args, **kwargs):
        self.age += 1
        if self.age *= 4:
            raise StopIteration("Stop")

        return self.age
p = Person()
pi = iter(p , 4)#iter的第一个参数是一个可调用函数 第二个参数是终止值
print(pi)
for i in pi:
    print(i)
'''
<callable_iterator object at 0x0000024C494A4D90*
2
3
'''

描述器

  • 可以描述一个属性操作的对象
  • 属性指向一个特殊的对象,该对象具有__set__,get,__delete__方法

定义

定义方式1:property
class Person:
    def __init__(self):
        self.__age = 18
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self, value):
        print("setter")
        if value < 0:
            value = 0
        self.__age = value
    @age.deleter
    def age(self):
        del self.__age
    #age = property(get_age, set_age, del_age)
p = Person()
print(p.age) #18
p.age = 19
print(p.age)#19
定义方式2
class Age:
    def __get__(self, instance, owner):
        print("get")
        return self
    def __set__(self, instance, value):
        print("set")
        self = value
    def __delete__(self, instance):
        print("delete")
        del self
class Person:
    age = Age()

p = Person()
print(p.age)
p.age = 19
  • 一个实例属性的正常访问顺序
  • 1.实例对象自身的__dict__字典
  • 2.对应类对象的__dict__字典
  • 3.如果有父类,会在父类的__dict__字典中检测
  • 4.如果没找到,但是有__getattr__方法,就会调此方法
  • 那么究竟是如何实现__get__的优先调用?
  • 内部:如果实现了描述器方法__get__就会直接调,没有就按照上述机制去查找
  • 资料描述器:get/set
  • 非资料描述器:仅仅实现了get方法
  • 资料描述器自身属性非资料描述器
采用属性类定义
class Age:
    #self是Age对象 instance是所定义的类对象
    #Age对象是在各个类对象之中共享的
    def __get__(self, instance, owner):
        print("get", instance, owner)
        return self.v
    def __set__(self, instance, value):
        print("set")
        self.v = value
    def __delete__(self, instance):
        print("delete")
        del self
class Person:
    age = Age()

p = Person()
p.age = 18 #get <__main__.Person object at 0x0000018F6805F1C0* <class '__main__.Person'*
print(p.age)#18
p2 = Person()
p2.age = 10
print(p2.age)#get <__main__.Person object at 0x0000018F680C8850* <class '__main__.Person'*10
print(p.age)#get <__main__.Person object at 0x0000018F680C8850* <class '__main__.Person'*10
class Age:
    #self是Age对象 instance是所定义的类对象
    #Age对象是在各个类对象之中共享的
    def __get__(self, instance, owner):
        print("get", instance, owner)
        return instance.v
    def __set__(self, instance, value):
        print("set")
        instance.v = value
    def __delete__(self, instance):
        print("delete")
        del self
class Person:
    age = Age()

p = Person()
p.age = 18 
print(p.age)
p2 = Person()
p2.age = 10
print(p2.age)
print(p.age)
'''
set
get <__main__.Person object at 0x000001A01723F1C0* <class '__main__.Person'*
18
set
get <__main__.Person object at 0x000001A0172A8850* <class '__main__.Person'*
10
get <__main__.Person object at 0x000001A01723F1C0* <class '__main__.Person'*
18
'''

对象的生命周期

class Person:
    def __new__(cls, *args, **kwargs):
        print("new可以拦截对象的创建")
    pass
    def __init__(self):
        print("对象创建")
    def __del__(self):
        print("该对象被释放了886")
p = Person()#new可以拦截对象的创建
print(p)#None
del p

内存管理机制

存储方面

  • python中无基本数据类型,都是对象
  • 所有对象,都会在内存中开辟一块空间进行存储(会通过不同的类型和内容,开辟不同的空间大小进行存储,同时会返回“引用”(地址),用于后续对象操作
  • 对于整数和短小的字符,python会进行缓存,不创建多个对象
  • 容器对象存储的其他对象,仅仅是其他对象的引用,而不是其他对象本身(列表,元组)

引用计数器机制

引用计数增加场景
  • 对象被创建
  • 对象被引用p2 = p1
  • 对象被作为参数被传到另外一个参数中去
  • 对象作为一个元素存储在容器中

垃圾回收机制(处理循环引用问题

  • 从经历过“引用计数器机制”仍未被释放的对象中找到循环引用并释放。
  • 分代回收机制
垃圾回收时机
  • 自动回收
  • 手动回收
import gc
print(gc.isenabled)()#默认开
gc.disable()#关闭
print(gc.isenabled())#false
#装饰器 谁在外层先执行谁
import win32com.client
speaker = win32com.client.Dispatch("SAPI.SpVoice")
speaker.Speak("Hello world")
class Caculater:
    def __say(func):
        def inner(self, num):
            speaker = win32com.client.Dispatch("SAPI.SpVoice")
            speaker.Speak(num)
            func(self, num)
        return inner

    def __init__(self):
        self.result = 0

    @__say
    def add(self, num):
        self.result = self.result + num
    @__say
    def sub(self, num):
        self.result = self.result - num
    @__say
    def mutiple(self, num):
        self.result = self.result * num
    @__say
    def div(self, num):
        self.result = self.result / num
caculator = Caculater()
caculator.add(5)
caculator.sub(10)

继承

  • 单继承:仅仅继承了一个父类
  • 多继承:继承了多个父类
class Animal:
    pass
class Dog:
    pass
class cute(Animal, Dog):#多继承
    pass
print(cute.__bases__)#(<class '__main__.Animal'*, <class'__main__.Dog'*)
print(bool.__bases__)#(<class 'int'*,)
print(int.__bases__)#(<class 'object'*,)
  • 继承机制下,私有属性和私有方法都不能继承!内置的方法可以继承。
  • 是继承了相关内容的访问权,而不是写入权。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GrZVkagk-1679875777914)(1.png “继承类别”)]

  • 单继承:从下往上找,先从自己找,再从父类,再父父类。
  • 无重叠的多继承链:先左链条往上再右链条往上,单调原则。
  • 有重叠的多继承链:先父类(左-右)再爷类
class Person:
    pass
class yawen(Person):
    pass
import inspect
print(inspect.getmro(yawen))#(<class '__main__.yawen'*, <class '__main__.Person'*, <class 'object'*)

资源累加

#super 沿着MRO链条找到下一级结点,去调用对应的方法
class B:
    def __init__(self):
        self.b = 1
    pass
class A(B):
    def __init__(self):
        super().__init__()
        self.a = 2
a = A()
print(a.__dict__)#{'b': 1, 'a': 2}

多态

  • 定义:一个类所能衍生出的多种形态,在继承的前提下,调用父类的同一个方法,产生不同的功能。
  • 多态一般是在静态语言里面实现的,python是动态语言,实质上没有真正的多态,也不需要多态。

抽象类

  • 一个抽象出来的类,不能直接创建实际的对象;抽象方法是一个抽象出来的方法,不具备具体的实现,也不能直接调用,子类不实现该方法会报错。

python中的实现

  • 无法直接支持,需要借助一个模块 import abc
  • 设置类的元类为abc.ABCMeta
  • 使用装饰器修饰抽象方法@abc.abstractmethod
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return "{}岁的小狗{}".format(self.age, self.name)

    def play(self):
        print("%s在玩" % self)

d = Dog("niko", 2)
d.play()#2岁的小狗niko在玩

面向对象设计原则

  • SOLID
  • S(Single Responsibility Principle)单一职责原则,一个类只负责一个职责。
  • O(Open Closed Principle)开放封闭原则:对扩展开放,对修改关闭
  • L(Liskov Substitution Principle)里氏替代方法:子类一定得具备父类的特性、方法
  • I(Interface Segregation Principle)接口分离原则,如果一个类具有过多的接口方法,并且这些方法在使用的过程中并非是不可分割,那么应当将他们分离。
  • D(Dependency Inversion Principle)依赖倒置原则:高层模块不应该直接依赖底层模块。# python面向对象

内置方法

__call__方法

  • 使得对象具备当作函数来调用的能力
class Person:
    def __call__(self, *args, **kwargs):
        print("xxx", args, kwargs)
    pass

p = Person()
p("hello")#xxx ('hello',) {}
class PenFactory:
    def __init__(self, p_type):
        self.p_type = p_type

    def __call__(self, p_color):
        print("类型:%s,  颜色%s" % (self.p_type, p_color))

gangbi = PenFactory("钢笔")
gangbi("绿色")
gangbi("红色")
'''
类型:钢笔,  颜色绿色
类型:钢笔,  颜色红色
'''

索引操作

  • 对一个实例对象进行索引操作
class Person:
    def __init__(self):
        self.cache = {}
    def __setitem__(self, key, value):
        #print("setitem", key, value)
        self.cache[key] = value
    def __getitem__(self, item):
        #print("getitem", item)
        return self.cache[item]
    def __delitem__(self, key):
        #print("delitem", key)
        del self.cache[key]
#想对对象进行类似字典的操作需要在里面定义内置的item函数
p = Person()
p["name"] = "niko" #setitem name niko
print(p.__dict__)#{'cache': {'name': 'niko'}}
print(p["name"])#niko
del p["name"]
print(p.__dict__)#{'cache': {}}

切片操作

class Person:
    def __init__(self):
        self.items = [1, 2, 3, 4]
    def __setitem__(self, key, value):
        print(key.start, key.stop, key.step, value)
        self.items[key] = value
    def __getitem__(self, item):
        print("getitem", item)
p = Person()
p[0 : 4 : 2] = ["a", "b"]
print(p.__dict__)
p[0 : 2]
'''
0 4 2 ['a', 'b']
{'items': ['a', 2, 'b', 4]}
getitem slice(0, 2, None)
'''

比较操作

  • 对于反向操作的比较运算符,如果只定义了其中一种方法,但是使用的是另外一种比较运算,系统会采用调换参数的方式进行方法调用。但是,不支持叠加操作。
import functools
@functools.total_ordering #会自动补全其他方式
class Person:
    def __init__(self, age, height):
        self.age = age
        self.height = height
    def __lt__(self, other):
        print(self.age, other.age)#采用调换参数实现
        return self.age < other.age#p1自动映射为self,p2映射为other
    def __eq__(self, other):
        return self.age == other.age

p1 = Person(18, 160)
p2 = Person(19, 240)
print(p1 < p2)#True
print(p1 * p2)#False
print(p1 == p2)#False
print(Person.__dict__)#{ '__lt__': <function Person.__lt__ at 0x0000022E1DBB4F70*, '__eq__': <function Person.__eq__ at 0x0000022E1DBB4EE0*}
print(Person.__dict__)
#: <function Person.__init__ at 0x0000022DD1554F70*, '__lt__': <function Person.__lt__ at 0x0000022DD1554EE0*, '__eq__': <function Person.__eq__ at 0x0000022DD155D040*,  '__gt__': <function _gt_from_lt at 0x0000022DD14D7AF0*, '__le__': <function _le_from_lt at 0x0000022DD14D7B80*, '__ge__': <function _ge_from_lt at 0x0000022DD14D7C10*}
print(p1 <= p2)#True 组合了小于和等于

上下文环境的布尔值

class Person:
    def __bool__(self):#代表了该类型对象的真假
        return False
    pass

p = Person()
print(bool(p))#False

遍历操作

  • 怎样可以使得我们自己创建的对象可以使用for in进行遍历?①实现__getitem__方法 ②实现__iter__方法
  • 怎样可以使得我们自己创建的对象可以使用next进行访问?
class Person:
    def __init__(self):
        self.result = 1
    def __getitem__(self, item):#要自行设置终止条件,不要死循环
        print("getitem")
        self.result += 1
        if self.result *= 6:
            raise StopIteration("停止遍历")
        return self.result
    def __iter__(self):#方式2优先级高于getitem
    #要返回迭代器,有next方法的对象才是迭代器
        return self
    def __next__(self):
        self.result += 1
        if self.result *= 6:
            raise StopIteration("停止遍历")
        return self.result
p = Person()
for i in p:
    print(i)
'''
2
3
4
5
'''
next访问对象
class Person:
    def __init__(self):
        self.result = 1
    def __next__(self):
        self.result += 1
        if self.result *= 6:
            raise StopIteration("停止遍历")
        return self.result
p = Person()
print(next(p))
'''
2
'''
  • 对象如为迭代器必须要实现iter和next俩个方法
class Person:
    def __init__(self):
        self.age = 1
    def __iter__(self):
        self.age = 1
        return self

    def  __next__(self):
        self.age += 1
        if self.age *= 3:
            raise StopIteration("Stop")

        return self.age

p = Person()
import collections
print(isinstance(p, collections.Iterator))#True
for i in p:
    print(i)
for i in p:
    print(i)
'''
2
2
'''
  • 迭代器只可以遍历一次,想多次使用需要在iter中进行回退操作,也就是初始化
  • getitem即使可以使用for in访问但是并不是可迭代对象
  • Iterable必须是要有iter方法
  • 可迭代对象一定可for in访问,反之不成立
class Person:
    def __init__(self):
        self.age = 1

    def __iter__(self):
        self.age = 1
        return self
    def __call__(self, *args, **kwargs):
        self.age += 1
        if self.age *= 4:
            raise StopIteration("Stop")

        return self.age
p = Person()
pi = iter(p , 4)#iter的第一个参数是一个可调用函数 第二个参数是终止值
print(pi)
for i in pi:
    print(i)
'''
<callable_iterator object at 0x0000024C494A4D90*
2
3
'''

描述器

  • 可以描述一个属性操作的对象
  • 属性指向一个特殊的对象,该对象具有__set__,get,__delete__方法

定义

定义方式1:property
class Person:
    def __init__(self):
        self.__age = 18
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self, value):
        print("setter")
        if value < 0:
            value = 0
        self.__age = value
    @age.deleter
    def age(self):
        del self.__age
    #age = property(get_age, set_age, del_age)
p = Person()
print(p.age) #18
p.age = 19
print(p.age)#19
定义方式2
class Age:
    def __get__(self, instance, owner):
        print("get")
        return self
    def __set__(self, instance, value):
        print("set")
        self = value
    def __delete__(self, instance):
        print("delete")
        del self
class Person:
    age = Age()

p = Person()
print(p.age)
p.age = 19
  • 一个实例属性的正常访问顺序
  • 1.实例对象自身的__dict__字典
  • 2.对应类对象的__dict__字典
  • 3.如果有父类,会在父类的__dict__字典中检测
  • 4.如果没找到,但是有__getattr__方法,就会调此方法
  • 那么究竟是如何实现__get__的优先调用?
  • 内部:如果实现了描述器方法__get__就会直接调,没有就按照上述机制去查找
  • 资料描述器:get/set
  • 非资料描述器:仅仅实现了get方法
  • 资料描述器自身属性非资料描述器
采用属性类定义
class Age:
    #self是Age对象 instance是所定义的类对象
    #Age对象是在各个类对象之中共享的
    def __get__(self, instance, owner):
        print("get", instance, owner)
        return self.v
    def __set__(self, instance, value):
        print("set")
        self.v = value
    def __delete__(self, instance):
        print("delete")
        del self
class Person:
    age = Age()

p = Person()
p.age = 18 #get <__main__.Person object at 0x0000018F6805F1C0* <class '__main__.Person'*
print(p.age)#18
p2 = Person()
p2.age = 10
print(p2.age)#get <__main__.Person object at 0x0000018F680C8850* <class '__main__.Person'*10
print(p.age)#get <__main__.Person object at 0x0000018F680C8850* <class '__main__.Person'*10
class Age:
    #self是Age对象 instance是所定义的类对象
    #Age对象是在各个类对象之中共享的
    def __get__(self, instance, owner):
        print("get", instance, owner)
        return instance.v
    def __set__(self, instance, value):
        print("set")
        instance.v = value
    def __delete__(self, instance):
        print("delete")
        del self
class Person:
    age = Age()

p = Person()
p.age = 18 
print(p.age)
p2 = Person()
p2.age = 10
print(p2.age)
print(p.age)
'''
set
get <__main__.Person object at 0x000001A01723F1C0* <class '__main__.Person'*
18
set
get <__main__.Person object at 0x000001A0172A8850* <class '__main__.Person'*
10
get <__main__.Person object at 0x000001A01723F1C0* <class '__main__.Person'*
18
'''

对象的生命周期

class Person:
    def __new__(cls, *args, **kwargs):
        print("new可以拦截对象的创建")
    pass
    def __init__(self):
        print("对象创建")
    def __del__(self):
        print("该对象被释放了886")
p = Person()#new可以拦截对象的创建
print(p)#None
del p

内存管理机制

存储方面

  • python中无基本数据类型,都是对象
  • 所有对象,都会在内存中开辟一块空间进行存储(会通过不同的类型和内容,开辟不同的空间大小进行存储,同时会返回“引用”(地址),用于后续对象操作
  • 对于整数和短小的字符,python会进行缓存,不创建多个对象
  • 容器对象存储的其他对象,仅仅是其他对象的引用,而不是其他对象本身(列表,元组)

引用计数器机制

引用计数增加场景
  • 对象被创建
  • 对象被引用p2 = p1
  • 对象被作为参数被传到另外一个参数中去
  • 对象作为一个元素存储在容器中

垃圾回收机制(处理循环引用问题

  • 从经历过“引用计数器机制”仍未被释放的对象中找到循环引用并释放。
  • 分代回收机制
垃圾回收时机
  • 自动回收
  • 手动回收
import gc
print(gc.isenabled)()#默认开
gc.disable()#关闭
print(gc.isenabled())#false
#装饰器 谁在外层先执行谁
import win32com.client
speaker = win32com.client.Dispatch("SAPI.SpVoice")
speaker.Speak("Hello world")
class Caculater:
    def __say(func):
        def inner(self, num):
            speaker = win32com.client.Dispatch("SAPI.SpVoice")
            speaker.Speak(num)
            func(self, num)
        return inner

    def __init__(self):
        self.result = 0

    @__say
    def add(self, num):
        self.result = self.result + num
    @__say
    def sub(self, num):
        self.result = self.result - num
    @__say
    def mutiple(self, num):
        self.result = self.result * num
    @__say
    def div(self, num):
        self.result = self.result / num
caculator = Caculater()
caculator.add(5)
caculator.sub(10)

继承

  • 单继承:仅仅继承了一个父类
  • 多继承:继承了多个父类
class Animal:
    pass
class Dog:
    pass
class cute(Animal, Dog):#多继承
    pass
print(cute.__bases__)#(<class '__main__.Animal'*, <class'__main__.Dog'*)
print(bool.__bases__)#(<class 'int'*,)
print(int.__bases__)#(<class 'object'*,)
  • 继承机制下,私有属性和私有方法都不能继承!内置的方法可以继承。
  • 是继承了相关内容的访问权,而不是写入权。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eJWOq5co-1679875778926)(1.png “继承类别”)]

  • 单继承:从下往上找,先从自己找,再从父类,再父父类。
  • 无重叠的多继承链:先左链条往上再右链条往上,单调原则。
  • 有重叠的多继承链:先父类(左-右)再爷类
class Person:
    pass
class yawen(Person):
    pass
import inspect
print(inspect.getmro(yawen))#(<class '__main__.yawen'*, <class '__main__.Person'*, <class 'object'*)

资源累加

#super 沿着MRO链条找到下一级结点,去调用对应的方法
class B:
    def __init__(self):
        self.b = 1
    pass
class A(B):
    def __init__(self):
        super().__init__()
        self.a = 2
a = A()
print(a.__dict__)#{'b': 1, 'a': 2}

多态

  • 定义:一个类所能衍生出的多种形态,在继承的前提下,调用父类的同一个方法,产生不同的功能。
  • 多态一般是在静态语言里面实现的,python是动态语言,实质上没有真正的多态,也不需要多态。

抽象类

  • 一个抽象出来的类,不能直接创建实际的对象;抽象方法是一个抽象出来的方法,不具备具体的实现,也不能直接调用,子类不实现该方法会报错。

python中的实现

  • 无法直接支持,需要借助一个模块 import abc
  • 设置类的元类为abc.ABCMeta
  • 使用装饰器修饰抽象方法@abc.abstractmethod
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return "{}岁的小狗{}".format(self.age, self.name)

    def play(self):
        print("%s在玩" % self)

d = Dog("niko", 2)
d.play()#2岁的小狗niko在玩

面向对象设计原则

  • SOLID
  • S(Single Responsibility Principle)单一职责原则,一个类只负责一个职责。
  • O(Open Closed Principle)开放封闭原则:对扩展开放,对修改关闭
  • L(Liskov Substitution Principle)里氏替代方法:子类一定得具备父类的特性、方法
  • I(Interface Segregation Principle)接口分离原则,如果一个类具有过多的接口方法,并且这些方法在使用的过程中并非是不可分割,那么应当将他们分离。
  • D(Dependency Inversion Principle)依赖倒置原则:高层模块不应该直接依赖底层模块
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值