一、__slots__和property
1.__slots__魔术函数动态的添加方法和属性
2.直接暴露属性的局限性
3.使用get/set方法
4.利用@property简化get/set方法
5.利用@property实现只读属性
6.装饰器与property实现
# import traceback
# from types import MethodType
#
# class MyClass(object):
# # pass
# #在做新的类的时候,限制动态添加的属性,这个时候需要用到__slots__魔术变量,系统内为了实现某些特定功能的
# __slots__ = ['name','set_name'] # 这个地方,能添加的属性和方法就会受到限制,只能添加name或者set_name这两个名词的属性或者方法
# def set_name(self,name):
# self.name = name
# cls = MyClass() #实例化类
# cls.name='Tom' #动态的添加属性
# cls.set_name=MethodType(set_name,cls) #动态的添加方法 将set_name作用于cls上面
# cls.set_name('Jerry')
# print(cls.name)
# try:
# cls.age= #动态添加属性 ,这个地方要注意,age不在__slots__规定的数组中,所以会报错
# except AttributeError:
# traceback.print_exc() #打印出异常信息 AttributeError: 'MyClass' object has no attribute 'age'
#
# class ExtMyClass(MyClass): #继承自MyClass
# pass
# ext_cls = ExtMyClass()
# ext_cls.age=
# print(ext_cls.age)
2.property
import traceback
class Student:
@property # 这个地方用装饰器进行修饰的时候,实际上是生成了一个新的对象,名字叫做score,这个相当于set函数
def score(self):
return self._score
@score.setter
def score(self,value):
if not isinstance(value,int): #进行value的类型检查,如果不是int型的值,就会报错not int
raise ValueError('not int') elif (value<) or (value>): #如果value只不是在这个区间之间的话,就会报错值不在0~100之间,这个地方相当于get函数
raise ValueError('not between 0 ~ 100')
self._score=value @property #注意,这里没有set方法,所以只能读取,不能写
def double_score(self):
return self._score*
s= Student()
s.score=
print(s.score)
print(s.double_score)
try:
s.double_score=
except AttributeError:
traceback.print_exc() try:
s.score='abc'
except ValueError:
traceback.print_exc()
try:
s.score=
except ValueError:
traceback.print_exc()
3.枚举类
from enum import Enum Month = Enum('Month',('Jan','Feb','Mar','Apr')) for name,member in Month.__members__.items():
print(name,'=>',member,',',member.value) jan = Month.Jan
print(jan)
二、元类
1.运行时动态创建 vs 编译时定义
def init(self,name): #自定义构造函数,
self.name=name
def say_hello(self): #自定义成员函数
print('hello, %s!' %self.name) Hello = type('Hello',(object, ),dict(__init__ = init,hello=say_hello)) #(object, )是一个基类的列表 """
这个地方的代码等价于下面的这些代码:
class Hello:
def __init__(.......)
def hello(..........)
"""
h = Hello('Tom')
h.hello()
2.使用type创建新类型
3.metaclass(元类)
(1)metaclass -> class -> instance
(2)继承和动态绑定可以解决问题吗?
(3)__new__函数
class ListMetaclass(type):
def __new__(cls,name,bases,attrs):
# print(cls) #打印出传进来的类时什么
# print(name) #打印出传进来的name是什么
# print(bases) #打印出传入进来的基类是什么 基类是list类
attrs['add'] = lambda self,value:self.append(value)
return type.__new__(cls,name,bases,attrs)
class MyList(list,metaclass=ListMetaclass): #从list类继承下来,就是一个数组,但是额外的增加add方法,实际等价于append
pass
mli = MyList()
mli.add()
mli.add()
mli.add()
print(mli)