元类
在python中一切皆对象,类也是对象,只不过类是一个创建对象的对象,我们可以在类中动态的创建一个类,比如
def
func(name):
if
name ==
"
Plane
"
:
class
Plane(object):
pass
return
Plane
else
:
class
Metrorolite(object):
pass
return
Mrtroolite
虽然根据上述代码可以动态创建一个类,但是整个类的代码仍需要我们编写的
type()有两种作用:
1、检查对象类型
class
People(object):
def
__init__
(self, id, name, employees):
self.id
=
id
self.name
=
name
def
func(self):
return
if
__name__
==
"
__main__
"
:
id
= 1001
name
=
"
abc
"
employees
= [1,2,3
]
people
=
People(id, name, employees)
#
检查整型
print
(type(id))
#
#
检查字符串型
print
(type(name))
#
#
检查列表型
print
(type(employees))
#
#
检查类的对象型
print
(type(people))
#
#
检查类类型
print
(type(People))
#
#
检查函数型
print
(type(people.func))
#
#
如果我们对其结果再次type()得到的结果都是type类型,这就验证了一切解释对象
2、还有一个高大上的作用就是动态的创建类
语法:type(类名, 由父类名称组成的元组(可以为空), 包含属性的字典(名称和值))
返回值是一个类
#
空类
Chinese = type(
"
People
"
, (), {})
#
继承父类,父类以元组的形式表达
Chinses = type(
"
People
"
, (object, ), {})
#
给类一些属性(下述都是类属性)和方法(方法可以自定义,依次是实例方法、类方法、静态方法)
def
sayHI(self):
print
(
"
HI
"
)
@classmethod
def
sayHello(cls):
print
(
"
Hello
"
)
@staticmethod
def
sayBye():
print
(
"
Bye
"
)
Chinese
= type(
"
People
"
, (object, ), {
"
id
"
: 1001,
"
name
"
:
"
zhangsan
"
,
"
func1
"
: sayHI,
"
func2
"
: sayHello,
"
func3
"
: sayBye})
#
Chinese 不是类名,People是类名,Chinese是一个引用变量
元类的定义:
元类就是用来创建类的“东西”
元类是类的类, 是类的模板
元类是用来控制如何创建类的, 正如类是创建对象的模板一样, 而元类的主要目的是为了控制类的创建行为
元类的实例化结果是我们用class定义的类,正如类的实例为对象
type是python的一个内建元类, 用来直接控制生成类
python中任何class定义的类其实都是type类实例化的对象
当然了,你也可以创建自己的元类,需要继承 type。
元类的定义和使用:
通过函数返回一个元类:
#
自定义函数
def
summary(a, b):
return
a+
b
#
这个函数的作用是修改当前类的属性的值和方法的功能,并且返回一个类
def
upper_attr(future_class_name, future_class_parent, future_class_attr):
#
可以修改当前类定义的属性的值和方法的功能
newAttr =
{}
for
name, value
in
future_class_attr.items():
if
name ==
"
bar
"
:
newAttr[name]
=
"
变量值修改了
"
if
name ==
"
func
"
:
newAttr[name]
=
summary
return
type(future_class_name, future_class_parent, newAttr)
class
Operation(object, metaclass=
upper_attr):
bar
=
"
修改之前的值
"
func
=
None
if
__name__
==
"
__main__
"
:
print
(Operation.bar)
#
变量值修改了
print
(Operation.func(2, 4))
#
返回值6
通过继承type生成元类(博主也没有看懂,了解即可,用到极少):
class
Meta(type):
def
__init__
(cls, *args, **
kwargs):
super().
__init__
(*
args)
def
__new__
(cls, *args, **kwargs):
name, bases, attrs = args
return super().__new__(cls, name, bases, attrs)
class M_Class(metaclass=Meta):
def __new__(cls, *args, **kwargs):
return super().__new__(cls)
def __init__(self):
pass
动态语言
静态语言和动态语言的区别:
静态语言(强类型语言)
静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要 求在使用变量之前必须声明数据类型。
例如:C++、Java、Delphi、C#等。
动态语言(弱类型语言)
动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明, 通常变量的类型是被赋值的那个值的类型。
例如:PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
动态语言的特性:
运行的过程中给对象绑定(添加)属性
运行的过程中给类绑定(添加)属性
运行的过程中给类绑定(添加)方法
运行的过程中删除属性、方法
class
Person(object):
def
__init__
(self, name, age):
self.name
=
name
self.age
=
age
def
show():
print
(
"
通过类动态增加类方法.
"
)
@classmethod
def
show2(cls):
print
(
"
通过类动态增加类方法,并且打印id.
"
, cls.id)
if
__name__
==
"
__main__
"
:
person
= Person(
"
张三
"
, 22
)
#
运行过程中,给对象添加属性
person.phone =
"
1847015XXXX
"
print
(person.phone)
#
1847015XXXX
#
运行过程中,对象是不能添加方法,否则会报错
#
person.func = show
#
person.func()
#
运行过程中,给类增加属性
Person.id = 10001
print
(
"
对象访问类属性
"
, person.id)
#
对象访问类属性10001
print
(
"
类访问类属性
"
, Person.id)
#
类访问类属性10001
#
运行过程中给类增加方法
Person.func =
show
Person.func()
#
通过类动态增加类方法.
#
运行过程中给类增加类方法
Person.func =
show2
Person.func()
#
通过类动态增加类方法,并且打印id。10001
__slots__
__slots__作用:
Python允许在定义class的时候,定义一个特殊变量__slots__来限制该 class能添加的属性,当前类就不能定义或者增加__slots__之外的属性了
__slots__注意事项:
__slots__只对类的实例化对象进行限制,不对类进行限制,__slots__变量值是以元组形式表示
__slots__不仅限制类对象的属性,还限制类对象的方法
__slots__仅对当前类起作用,对继承的子类不起作用
在子类中定义__slots__,子类允许定义的属性就是自身的__slots__加上父类的 __slots__
class
Person(object):
__slots__
= (
"
name
"
,
"
age
"
)
def
__init__
(self, name, age):
self.name
=
name
self.age
=
age
if
__name__
==
"
__main__
"
:
person
= Person(
"
张三
"
, 22
)
#
运行过程中,给对象添加属性实例对象属性只限于name,age
#
person.phone = "1847015XXXX"
#
print(person.phone)
#
运行过程中,给类增加属性,__slots__ 不限制类
Person.id = 10001
print
(
"
对象访问类属性
"
, person.id)
#
对象访问类属性 10001
print
(
"
类访问类属性
"
, Person.id)
#
类访问类属性 10001
生成器
概念:Python中,这种一边循环一边计算的机制,称为生成器:generator。
创建生成器的两种方式:
方法1:列表生成式的 [ ] 改成 ( )
numbers = ( i for i in range(100))
通过 next() 函数获得生成器的下一个返回值
没有更多的元素时,抛出 StopIteration 的异常
正确的方法是使用 for 循环,因为生成器也是可迭代对象,并且不需要关心 StopIteration 异
方法2:使用函数创建生成器(实例)
#
斐波那契数列
def
fibonacci(num):
a
=
0
b
= 1
count
=
0
temp
= 1
while
count <
num:
yield
b
a, b
= b, a+
b
count
+= 1
fi
= fibonacci(4
)
print
(next(fi))
#
1
print
(next(fi))
#
1
print
(next(fi))
#
2
print
(next(fi))
#
3
#
没有更多的元素时,抛出 StopIteration 的异常
#
正确的方法是使用 for 循环,因为生成器也是可迭代对象,并且不需要关心StopIteration 异常
print
(next(fi))
#
error
#
所以在使用生成器的时候,需要捕获异常
fi = fibonacci(10
)
while
True:
try
:
print
(next(fi))
except
StopIteration as e:
print
(e)
break
另外生成器也可以传递参数通过send(参数值):
#
斐波那契数列
def
fibonacci(num):
a
=
0
b
= 1
count
=
0
temp
= 1
while
count <
num:
temp
=
yield
temp*
b
print
(
"
temp{}:{}
"
.format(count, temp))
a, b
= b, a+
b
count
+= 1
fi
= fibonacci(10
)
print
(next(fi))
while
True:
try
:
print
(fi.send(1
))
except
:
break
迭代器
可迭代对象:
这里先提一下迭代器对象,如果一个对象可以通for循环进行遍历的对象一般都是迭代器对象;python提供了一个Iterable类就是鉴别对象是否是迭代器对象,在鉴别的过程中需要借助isinstance()方法,这个方法是鉴别对象是否属于一个类的对象,这里不能用type()方法,因为type()的作用是鉴别对象是否是类的实例化对象(通过继承的是false)
首先先简单介绍两者检验对象类型的区别:
class
A:
def
__init__
(self):
pass
class
B(A):
def
__init__
(self):
super().
__init__
()
if
__name__
==
"
__main__
"
:
a
= 123
#
两者检验整型,类似这种,字符串、列表、元组、集合、字典都是一样的结果
print
(type(a) == int)
#
True
print
(isinstance(a, int))
#
True
#
两者主要的区别 直接通过类生成的对象,两者检验的结果是一样的
b =
B()
print
(type(b) == B)
#
True
print
(isinstance(b, B))
#
True
#
若是父类就会有不一样的结果
print
(type(b) == A)
#
False
print
(isinstance(b, A))
#
True
所以在检验对象时,采用isinstance()比较好,
from
collections
import
Iterable
class
A:
def
__init__
(self):
pass
class
B(A):
def
__init__
(self):
super().
__init__
()
#
实例生成器函数
def
func(self, a):
yield
a
a
= a + 1
if
a == 5
:
return
if
__name__
==
"
__main__
"
:
b
=
B()
print
(isinstance(b, Iterable))
#
False
#
像集合数据类型都是可迭代对象,字符串、列表、元组、集合、字典
b =
""
print
(isinstance(b, Iterable))
#
True
#
前面提到的生成器,他也是可迭代对象
a =
B()
b
=
a.func(0)
print
(isinstance(b, Iterable))
#
True
迭代器:
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用 isinstance() 判断一个对象是否是 Iterator 对象:
有两种情况是迭代器:
1、通过生成器函数生成的生成器就是迭代器
2、通iter()函数将可迭代对象转换成迭代器
from
collections
import
Iterator
class
A:
def
__init__
(self):
pass
class
B(A):
def
__init__
(self):
super().
__init__
()
#
实例生成器函数
def
func(self, a):
yield
a
a
= a + 1
if
a == 5
:
return
if
__name__
==
"
__main__
"
:
b
=
B()
print
(isinstance(b, Iterator))
#
False
#
像集合数据类型都是可迭代对象,字符串、列表、元组、集合、字典
b =
""
print
(isinstance(b, Iterator))
#
True
#
前面提到的生成器,他也是可迭代对象
a =
B()
b
=
a.func(0)
print
(isinstance(b, Iterator))
#
True
#
通过iter()函数将字符串、列表、元组、集合、字典转换成迭代器
b =
{}
b
=
iter(b)
print
(isinstance(b, Iterator))
迭代器是可以自定义,只要重写迭代器协议的两个方法
迭代器对象符合迭代器协议,提供两种方法: __iter__() 和 __next__()
__iter__ 返回迭代器对象,并在循环开始时隐式调用。
__next__方法返回下一个值,并在每个循环增量处隐式调用。
__next__在没有更多值返回时引发StopIteration异常,循环结构隐式捕获该 异常以停止迭代。
class
Counter:
def
__init__
(self, low, high):
self.current
=
low
self.high
=
high
#
生成器的一般固定写法
def
__iter__
(self):
return
self
#
在下面函数可以改变迭代器返回的下一个值
def
__next__
(self):
if
self.current >
self.high:
raise
StopIteration
else
:
self.current
+= 2
return
self.current -2

