Define class in Python
1. 面向对象
面向对象是一种思考角度, 做法: 将万物抽象成类.
2. class
class是抽象的概念, 是万事万物的abstract, 是一类事物共同特征的集合, 就是attribute和method的集合. object
是class的具象化, 是一个instance.
如有一个class是人类, 人类这个类可以创造出一个个instance, 也就是一个个人:
人名 = 人类(属性)
身高体重肺活量是这个人的attribute:
人名.身高
人名.体重
吃饭睡觉papapa是这个人的method:
人名.睡觉()
人名.吃饭(食物)
#这里的食物是另一种class的instance, 这个类就是都是能吃的东西, 也就是说一个class的instance可以和另一个class的instance相互作用
#同种类之间的实例, 也可以相互作用, 比如: dict1.update(dict2)
attribute, 是对对象状态的抽象, 用数据结构来描述.
method, 是对对象行为的抽象, 用操作名和实现该操作的方法来描述.
对象是数据和操作的封装.
3. 封装, 继承和多态
python 不存在多态.
一张图自己意会一下吧.
4. class of Python
4.1 define
class ClassName:
name = 'NAME'
def foo(self):
print(self)
这样就define了一个class, 把这个class和define时用的ClassName绑定起来.
‘name’ is attribute of this class, foo是class的method, but we only can call it through an instance of this class.
4.2 make instance
a = ClassName()
#attention, creat an instance needs call this class
Creat an instance equal to call .__init__(self, ….), it is exists in every class define procession and can make an instance of its params as instance’s attributes.
__init__ also has no return.
__init__ ‘s first param must be self.
method和function的区别, 本质区别就是一个是在类的内部定义, 一个不是.
__new__(cls, *args, **kwargs) 方法:
这个是实例化的类方法, python设定好的
4.3 class variable and instance variable
class Person:
age = 3 #这个就是类变量(就是类的属性)
def __init__(self, name):
self.name = name #这个就是实例变量(就是实例的属性)
4.4 class attribute and instance attribute
特殊属性:
.__name__ : 对象名, 类对象有名字, 但是实例对象没有自己的名字.
.__class__ : 对象的类, 实例对象有自己的类, 相当于type(object), 都返回类.
.__dict__ : 对象属性的字典, 类的字典要和实例的字典区分开来
.__qualname__ : 点示法显示函数名称、所在的类、模块等梯级地址
.__module__ : 看这个对象是哪个模块下的, 主模块是’main’
.__wekref__ : ????
.__globals__ : 对类的方法使用, 返回一个字典, 里面是全局下定义的所有的变量.
4.5 The Squence of Searching Instance Attribute
用实例来访问属性, 访问的字典是(但是实际操作不一定是这样的, 就这样理解):
实例.__dict__ = 类.__dict__.update(实例.__dict__)
访问类的属性, 并进行修改, 只是修改了类的属性的__dict__, 实例的属性没有改变. 但是用实例调用类的这个改变过得类的属性, 根据上面的规律, 得到的值当然是修改过的.
通过实例来访问类属性, 并进行修改是不会修改类的属性的, 但是这个被修改过得实例属性会保存下来, 记在实例的__dict__里.
总结就是, 只有修改了实例的属性值(实例属性或者类属性), 实例的__dict__就会相应的更新value或者增添key-value pair.
4.6 Decorator of class
例:
class ClassName:
def function1():
block
def function2(self):
block
function1的参数里不写self, 意味着这个函数必须通过类来访问, 通过实例无法访问
类调用function1, 不需要传参, Person.function1(), 就是简单的函数调用
类调用function2, 需要传参, 两种调用方式, Person.function2(Person()) 和 Person().function2(), 前者是给self传了一个参数Person(), 后者是把前面的对象Person(), 当做实参传给self
def addfuck(cls):
cls.fuck = 'fuck'
return cls
@addfuck # T = addfuck(T)
class T:
name = 'T'
def __init__(self, t):
self.t = t
a = T('t')
a.__dict__ # {'t': 't'}
T.__dict__
# mappingproxy({'__module__': '__main__',
'name': 'T',
'__init__': <function __main__.T.__init__(self, t)>,
'__dict__': <attribute '__dict__' of 'T' objects>,
'__weakref__': <attribute '__weakref__' of 'T' objects>,
'__doc__': None,
'fuck': 'fuck'})
总结@classmethod和@staticmethod是改变传参方式的,
前者: 如果用实例来调用, 第一个参数传入这个实例的类; 用类来调用, 第一个参数直接传入这个类
后者: 无论用实例还是用类来调用, 都不会把调用者当成第一参数传入(就是删除了第一个隐式传入的第一个参数)
如果这两个装饰器都不加, 用实例来调用, 就把实例当成第一参数传入, 用类来调用, 必须手动在()中传入实例.
属性装饰器:
@property 获取装饰器getter, 可以把私有属性, 按平常的形式访问, 把属性变成只读
@x.setter 修改装饰器, 可以按平常形式修改私有属性, 但是前面必须有getter就是必须有@property
@x.deleter 删除装饰器, 可以把私有属性删除
4.7 private attribute and protected attribute
在__init__() 中定义的实例属性, self.__属性名, 就会把这个属性变成私有属性
例:
class Test:
def __init__(self, a, b):
self.a = a
self.b = b
self.__c = 100
def getc(c)
return self.__c
__c就是私有属性, 直接用.c修改, 不好使, 因为内部自动给这个c改名了, 改成了_Test__c, 用这个名一样也能改.
4.8 other
__del__是在类定义时候放在里面的, 表示在这个类的实例消亡的时候, 把实例内部调用的资源都关闭了