类与对象
类是抽象的模版,对象是类的实例。
对象 = 属性 + 方法
- 封装、继承、多态
self
python的self
相当于c++的this
指针`。表示创建的实例本身。
在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
# <__main__.Test object at 0x000000BC5A351208>
# <class '__main__.Test'>
python的魔法方法
在Python中以两个下划线开头的方法,__init__
、__str__
、__doc__
、__new__
等,被称为"魔术方法"(Magic methods)。该方法在类实例化的时候会自动调用。
Python中的魔法方法可以理解为:对类中的内置方法的重载,注意这里不是重写。
重载和重写的区别:
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
e.g.
class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball("球A")
b = Ball("球B")
c = Ball("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...
公有和私有
在 Python 中定义私有变量只需要在变量名或函数名前加上“__”两个下划线,那么这个函数或变量就会为私有的了,比如__example
,类似c++的private。
继承
python中,派生类的定义如下:
class DerivedClassName(BaseClassName): # BaseClassName基类名,必须与派生类定义在一个作用域内。
<statement-1>
.
.
.
<statement-N>
除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:
class DerivedClassName(modname.BaseClassName):
<statement-1>
.
.
.
<statement-N>
子类除了可以继承父类的方法,还可以覆盖父类的方法:
class Animal():
def sound():
print("sound")
class Dog():
def sound():
print("汪")
class Cat():
def sound():
print("喵")
dog = Dog()
cat = Cat()
dog.sound()
cat.sound()
# 输出
# 汪
# 喵
- super()函数
super().__init__()
在单类继承中,super()函数用于指向要继承的父类,且不需要显式的写出父类名称。但是在多类继承中,会涉及到查找顺序(MRO)、钻石继承等问题。MRO 是类的方法解析顺序表, 也就是继承父类方法时的顺序表。在python中一般不使用多继承,易引起混乱。
super函数具体参考这一篇,自己做个记号
绑定
Python 严格要求方法需要有实例才能被调用,这种限制其实就是 Python 所谓的绑定概念。
Python 对象的数据属性通常存储在名为.__ dict__
的字典中,我们可以直接访问__dict__
,或利用 Python 的内置函数vars()获取.__ dict__
。
魔法方法
魔法方法的第一个参数应为cls(类方法) 或者self(实例方法)。
cls:代表一个类的名称
self:代表一个实例对象的名称
基本魔法方法
-
__init__(self[, ...])
,实例被创建时调用的初始化方法。 -
__new__(cls[, ...])
在一个对象实例化的时候所调用的第一个方法,在调用__init__
初始化前,先调用__new__
。
__new__
至少要有一个参数cls,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给__init__。
__new__
对当前类进行了实例化,并将实例返回,传给__init__的self。但是,执行了__new__,并不一定会进入__init__,只有__new__返回了,当前类cls的实例,当前类的__init__才会进入。
__new__方法主要是当你继承一些不可变的 class 时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。 -
__del__(self)
析构器,当一个对象将要被系统回收之时调用的方法。
参考:
魔法方法