一.类的成员描述符(属性)
#属性案例
#创建Student类,具有Student.name属性,但name格式不统一
#可以增加一个函数然后自动调用,但是麻烦
class Student():
def __init__(self,name,age):
self.name = name
self.age = age
self.setName(name) #不自己调用的话每执行一个对象就得调用一次
def intro(self):
print('hi,my name is {0}'.format(self.name))
def setName(self,name):
self.name = name.upper() #全变成大写
s1 = Student('Liu hh',18)
s2 = Student('hh liu',18)
s1.intro()
s2.intro()
1.类的成员描述符是为了在类中对类成员属性进行相关操作而创建的一种方式
- get:获取属性操作
- set:修改或添加属性操作
- delete:删除属性操作
2.如果想使用类的成员描述符,大概有三种方法
- 使用类实现描述器 (略):适用于多个类的多个属性共用一个描述符
- 使用属性修饰符 (略):适用于当前类,控制一个类的一个属性
- 使用property函数(简单):适用于当前类,控制一个类中多个属性
x = property(fget,fset,fdel,doc)
fget -- 获取属性值的函数,对变量进行读操作时执行
fset -- 设置属性值的函数,对变量进行写操作时执行
fdel -- 删除属性值函数,删除变量时执行
doc -- 属性描述信息
#property案例:
class Student():
def __init__(self):
self.name = 'ha'
def fget(self):
print('我被读取了,并执行了以下操作')
return self._name.upper()
def fset(self,name):
print('我被写入了,并执行了以下操作')
self._name = name*2
def fdel(self):
self._name = "noname"
name = property(fget,fset,fdel,'对name的操作(这是一个说明文档)')
s = Student()
print(s.name)
s.name = 'liu' #赋值时会调用fset方法,即name变为大写
print(s.name) #读取时会调用fget方法,即name*2
二.类的内置属性
- __dict__:以字典形式现实类的成员组成
- __doc__:获取类的文档信息
- __name__:获取类的名称,如果在模块中使用,获取模块的名称
- __bases__:获取某个类的所有父类,以元组形式显示
class A():
'''
这是类的说明文档
用单引号(单行)或三引号(多行)括起来表示
'''
pass
print(A.__dict__)
print(A.__doc__)
print(A.__name__)
print(A.__bases__)
三.类的常用魔术方法
1.魔术方法不需要人为调用,在特定的时刻自动触发
2.魔术方法统一特征:方法名被前后各两个下划线包裹,如__init__
- __new__ 对象实例化方法,较特殊,一般不使用
- __call__ 对象当函数使用的时候触发
- __str__ 当对象被字符串使用时触发这个函数,面向用户,便于阅读
- __repr__ 返回字符串 ,面向程序员,便于调试
class A():
def __init__(self):
print('我被调用了')
def __call__(self, *args, **kwargs):
print('我被当函数调用了')
def __str__(self):
return '这是返回的字符串'
a = A() #调用init
a() #调用call
print(a) #调用str
3.描述符相关 (再查资料)
- __set__
- __get__
- __delete__
4.属性操作相关
- __getattr__ 访问一个不存在的属性时触发
class A():
name = 'liu'
age = 18
def __getattr__(self, item): #把不存在的属性名传给item
print('{0}属性不存在'.format(item))
a = A()
print(a.addr)
- __setattr__ 对成员属性进行设置时触发
参数:self:用来获取当前对象,name:被设置的属性名称以字符串形式出现,value:被设置的属性的值
作用:进行属性设置的时候进行验证或修改
注意:该方法中不能对属性直接进行赋值操作,否则进入死循环
class A():
def __init__(self):
pass
def __setattr__(self, key, value):
print('设置属性:{0}'.format(key))
#下面语句会导致死循环
self.key = value
a = A()
a.age = 18
class A():
def __init__(self):
pass
def __setattr__(self, key, value):
print('设置属性:{0}'.format(key))
#下面语句会导致死循环
#self.key = value
#此种情况为了避免死循环,规定统一调用父类魔法函数
super().__setattr__(key,value)
a = A()
a.age = 18
5.运算分类相关
__gt__ 进行大于判断是触发的函数
self表示当前对象,第二个参数是第二个对象,返回值可以是任意值,推荐返回布尔值
class A():
def __init__(self,age):
self.age = age
def __gt__(self, other):
print('{0}会比{1}大吗'.format(self,other))
return self.age > other.age
a = A(18)
b = A(17)
print(a > b)
四.类和对象的三种方法 (区别再查资料)
1.实例方法:需要实例化对象才能使用的方法
2.静态方法:不需要实例化,通过类直接访问
3.类方法:不需要实例化
class A():
#实例方法
def eat(self):
print(self)
print('eat')
#类方法,第一个参数一般命名为cls,区别于self
@classmethod
def play(cls):
print(cls)
print('play')
#静态方法,不需要第一个参数表示自身或者类
@staticmethod
def say():
print('say')
a = A()
#a可以访问实例方法、类方法、静态方法
a.eat()
a.play()
a.say()
#类方法
A.play()
#静态方法
A.say()
五.抽象类
1.抽象方法:没有具体实现内容的方法
2.意义:规范子类的行为和接口
class Animel():
def sayHello(self): #规范代码,其实也可以不写
pass
class Dog(Animel):
def sayHello(self):
print('汪汪')
class People(Animel):
def sayHello(self):
print('hello')
d = Dog()
d.sayHello()
p = People()
p.sayHello()
3.抽样类:包含抽象方法的类叫抽象类,或abc类,抽样类的使用需要借助abc模块
import abc
抽象类的实现:
import abc
#声明一个抽象类,并且指定当前类的方法
class A(metaclass=abc.ABCMeta):
#定义一个抽象方法
@abc.abstractmethod
def say(self):
pass
#定义类抽象方法
@abc.abstractclassmethod
def drink(self):
pass
#定义静态抽象方法
@abc.abstractstaticmethod
def play(self):
pass
#定义具体方法
def sleep(self):
pass
抽象类的使用:
- 抽样类可以包含抽象方法,也可以包含具体方法,抽象类可以有方法也可以有属性
- 抽象类不允许直接实例化,必须继承才可以使用,且继承的子类必须实现所有继承来的抽象方法,若没有,则子类也不能实例化
- 抽象类的主要作用是设定类的标准,以便于开发的时候具有统一的规范
六.自定义类
1.类其实是一个类定义和各种方法的自由组合
#自己组装一个类
class A():
pass
def say(self):
print('say')
say(1)
A.say=say
a = A()
a.say()
原理:函数名可以当变量使用
def say(name):
print('{},hello'.format(name))
talk = say #函数名可以当变量使用
talk('kk')
上边是用类绑定了一个函数,如果直接用实例绑定一个函数时会出错,必须调用MethodType
from types import MethodType
class A():
pass
def say(self):
print('hello')
a = A()
a.say = MethodType(say,A)
a.say()
2.用type自定义类
help(type):
name:名称 bases:元组形式写父类 dict:字典形式写属性和方法
#利用type创建类
#先定义几个成员函数
def say(self):
print('say')
def sleep(self):
print('sleep')
A = type('Aname',(object,),{'aSay':say,'aSleep':sleep})
a = A()
a.aSay()
3.用元类自定义类 MetaClass
元类是类,被用来创建别的类,元类写法固定,必须继承自type
__new__()
方法接收到的参数依次是:
-
当前准备创建的类的对象;
-
类的名字;
-
类继承的父类集合;
-
类的方法集合。
class AMetaClass(type):#元类名称一般以MetaClass结尾
#注意以下写法是固定的
def __new__(cls, name, bases, attrs):
#自己要进行的操作
print('我是元类')
attrs['id']='666'
attrs['addr']='china'
return type.__new__(cls, name, bases, attrs)
#元类定义完就可以使用,使用方法注意:
class Student(object,metaclass=AMetaClass):
pass
s = Student()
print(s.id)
视频参考图灵学院