Python中的高级特性挺多的,在这里提到的只是微不足道的部分,只要是看起来比较好的特性,不管是新想到的,还是借鉴于其他语言的。只要好用,语言开发者都是可以加的。因为Python有自己的特性,它新加的一些功能看起来和其他语言有些不同,但是只要能明白这个特性能给我们的编程带来好处就行,能够优化我们的编程,为什么不用呢?
__slots__
python作为一门动态语言,给我的感觉,对于一个对象,感觉可以往对象上加入任何东西(属性、方法)一样。这个的好处就是扩展容易,极大的灵活,但是呢,越灵活,控制能力越低,有点不太安全。。在Python中,提供了一个特殊的变量:__slots__,它可以限制定义的变量。例子如下:
class A(object):
#表示A的实例只能定义name,age,method1这三个变量,其他的会报错,当然了,直接通过类名A来定义其他变量是可以的
__slots__ = ('name', 'age', 'method1')
def __init__(self, name):
self.name = name
#这里不能定义method1,提示和__slots__中的method1冲突
# def method1(self):
# print('i am method1')
#method2方法中没有self,因此这个方法不能通过类的实例进行调用,但是可以直接通过类名进行调用。
def method2():
print('i am method2')
#下面看使用
a = A('jcw')
a.age = 25 #成功赋值
a.name = 'jxr' #成功赋值
a.score = 100 #出错了。。
A.score = 100 #成功赋值
def m():
print('i am m')
a.method1 = m #成功赋值
a.method1() #返回: i am m
@property
装饰器模式,大家基本都听过吧,就算没有听过,也能猜出这种模式的作用。比如已经定义好了一个函数,我们想在函数执行之前或之后新增一些功能,给这个函数稍微的修饰一下,扩展一下。在Java中主要就是通过接口来实现装饰器模式的,而在python中,使用类似@property这个格式来实现的。例子如下:
class Student(object):
#@property相当于装饰器
@property
def score(self):
return self._score
#@score.setter相当于装饰器
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
student = Student()
#上面两个装饰器是python中自带的,_score的调用和赋值通过上面的装饰器,其实间接的会调用上面的两个函数
#这个赋值语句会调用@score.setter修饰的函数
student.score = 100
#@这个取值函数会调用@property修饰的函数
student.score
如何定制一个类?
在python中,class中有许多特殊用途的函数,通过重写这些函数,我们可以定制我们需要的类。
__len__():当我们在调用len()函数时,内部其实调用的就是__len__()函数
__str__():当我们调用print()等打印一个实例时,其实调用的就是__str__(),通过重写这个函数,可以打印比较容易读的格式。
__repr__():当直接在交互界面输入实例名时,调用的是__repr__()函数,为了显示美观,可以使__repr__ = __str__
__iter__():如果一个类想用于for…in循环,可以在类中实现这个函数,在循环过程中,会调用类中的__next__()函数,因此,也需要实现__next__()函数
__getitem__():实现这个方法,可以实现像list那样通过下标取元素
__getattr__():实现这个方法,当调用的属性不存在时,可以再调用这个函数。
__call__():可以实现在类本身上进行调用。即:s = Student(); s()写法会调用__call__()函数。
如何不通过class方式来定义一个类?
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。
type()
使用type()来创建一个类,跟class方式一样,例子如下:
def f(self):
print('hello, world')
#通过这种写法创建一个类,其中第一个参数表示类名,第二个参数表示父类构成的元组,第三个参数时一些变量构成的字典。
Hello = type('Hello', (object, ), dict(hello = f))
h = Hello()
h.hello() #输出hello, world
metaclass
metaclass感觉和Java中的Class类挺像的,Class类的实例相当于是我们定义的每一个类。
在使用中,先定义metaclass,就可以创建类,再创建实例。
这个东西比较复杂,也没仔细看,下面列举个简单的例子:
#先定义一个元类,元类都是从type类型进行派生的
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)
#定义我们的类,指定metaclass为我们自己定义的。
#通过指定metaclass,表示MyList需要通过ListMetaclass.__new__()来创建。
#其中__new__()函数中的四个参数依次为:当前准备创建类的对象、类名、类的父类、类的方法的集合
class MyList(list, metaclass=ListMetaclass):
pass
myList = MyList()
myList.add(1) #返回值为:[1]