一、元类
1、在大多数编程语言中,类就是一组用来描述如何生成一个对象代码段。在Python中这一点仍然成立,但是Python中的类还远不止如此,类同样也是一种对象。使用关键字class,Python解释器子啊执行的时候就会 创建一个对象。
Python一切皆对象
Linux一切皆文件
2、类的本质是对象,于是可以对类做如下的操作:
- 你可以将它赋值给一个变量
- 也可以拷贝它
- 可以增加属性
- 可以将它作为函数参数进行传递
class Date(object):
pass
# 1. 你可以将它赋值给一个变量
date = Date
print(date)
# 2.你可以拷⻉它
import copy
date2 = copy.deepcopy(Date)
print(id(Date))
print(id(date2))
# 3. 你可以为它增加属性
Date.year = 2019
print(Date.year)
# 4. 你可以将它作为函数参数进行传递
def fun(cls):
print(cls)
fun(Date)
3、type还有一种完全不同的功能,动态的创建类。
type可以接受一个类的描述作为参数,然后返回一个类
4、type(类名, 由父类名称组成的元组(针对继承的情况,可以为空),包含属 性的字典(名称和值))
- Foo = type(‘Foo’,(),{‘chen’:20})
- Foostudent = type(‘Foostudent’,(Foo,),{})
5、type创建带有方法的类
只需定义一个有着恰当签名的函数并将其作为属性赋值就可以了
- 添加类方法
- 添加实例方法
- 添加静态方法
class Student(object):
name = 'chen'
# 如何动态创建类? (基于元类创建的;)
MathStudent = type('MathStudent', (Student, ), {'country': 'china'})
print(MathStudent)
print(MathStudent.__bases__)
print(MathStudent.__dict__)
print(MathStudent.country)
print(MathStudent.name)
在python中,类也是对象,你可以动态的创建类。这就是当你使用关键字Class的时候python在幕后做的事情,而这就是通过元类来实现的。
6、元类就是用来创建类的“东西”。函数type实际上就是一个类。type就是Python在背后用来创建所有类的元类。
python的所有东西都是对象。而且它们都是从一个类创建而来,这个类就是type。
7、我们可以定义一个类的时候为其添加__metaclass__属性。python就会在类的定义中寻找__metaclass__属性,如果找到了,python就会用它来创建类Foo,如果没有找到,就会用内建的type来创建这个类。可以在__metaclass__中放置Django(ORM)
def upper_attr(cls_name, bases, attr):
"""
:param cls_name: 类名称
:param bases: 父类名称(元组)
:param attr: 属性(字典)
:return:
"""
newAttr = {}
for key, value in attr.items():
newAttr[key.upper()] = value
print(newAttr)
return type(cls_name, bases, newAttr)
# python3的写法
class Student(object, metaclass=upper_attr):
# 自定义指定元类名称
# python2:
# __metaclass__ = upper_attr
country = 'china'
score = 100
s = Student()
# print(s.country)
print(s.COUNTRY)
print(s.SCORE)
元类本省而言:
- 拦截类的创建
- 修改类
- 返回修改后的类
二、python是动态语言
1、 动态编程语言是 高级程序设计语言的一个类别,在计算机科学领域已被广泛应用。
它是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有
的函数可以被删除或是其他结构上的变化。动态语言目前非常具有活力。例如JavaScript便
是一个动态语言,除此之外如PHP、Ruby、Python等也都属于动态语言,而C、C++等语言则
不属于动态语言。
from prettytable import PrettyTable
# 自省功能
# 判断;类里面是否包含指定的属性?
print(hasattr(PrettyTable, '__doc__'))
print(hasattr(PrettyTable, 'a'))
# 获取指定属性对应的内容;
print(getattr(PrettyTable, "__bases__"))
# print(getattr(PrettyTable, "a"))
# 设置指定的属性, 动态添加属性信息的
setattr(PrettyTable, 'a', 1)
print(getattr(PrettyTable, 'a'))
@staticmethod
def test():
print("这是一个测试方法")
if hasattr(PrettyTable, 'test'):
print(getattr(PrettyTable, 'test'))
else:
print("正在动态添加方法:")
setattr(PrettyTable, 'test', test)
print(getattr(PrettyTable, 'test'))
test = getattr(PrettyTable, 'test') # 返回的时函数名
test()
print(hasattr(PrettyTable, 'a'))
print("正在删除属性")
delattr(PrettyTable, 'a')
print(hasattr(PrettyTable, 'a'))
2、给类添加方法,是使用类名.方法名=xxx,那么给对象添加方法是对象.方法名=xxx
- 对象.方法名=type.MethodType
- 类名.方法名=方法名
3、删除的方法:
- del 对象.属性名
- delattr(对象, “属性名”)
三、__slots__变量
1、动态语言:可以在运行的过程中,修改代码
静态语言:编译时已经确定好代码,运行过程中不能修改
2、在定义class的时候,定义一个特殊的__slots_变量,来限制class实例能添加的属性
使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。
class MyCounter(object):
# 限制属性的添加, 只能添加count和age;
__slots__ = ('count', 'a','c')
print(hasattr(MyCounter, 'a'))
counter = MyCounter()
counter.a = 1
print(counter.a)
# counter.b = 2
# print(counter.b)---->报错
counter.c = 3
print(counter.c)