Python——类的高级主题

介绍关于类的一些高级主题,这些是可选的,在Python应用程序中,不会常常遇到。

==========================================================================

slots实例

将字符串属性名称顺序赋值给特殊的__slots__类属性。就能够限制类的实例将有的合法属性集。

这个特殊属性通常是在class语句顶层内将字符串名称顺序赋值给变量__slots__而设置:仅仅有__slots__列表内的这些变量名可赋值为实例属性。而实例属性名必须在引用前赋值,即使是列在__slots__中也是这样。看下述样例:

>>> class limiter(object):
	__slots__ = ['age','name','job']

>>> x = limiter()
>>> x.age
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    x.age
AttributeError: age
>>> x.age = 40
>>> x.age
40
>>> x.ape = 1000
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    x.ape = 1000
AttributeError: 'limiter' object has no attribute 'ape'

假设创建了非常多实例而且仅仅有几个属性是必需的话。那么为每一个实例对象分配一个命名空间字典可能在内存方面的代价过于昂贵。要节省空间和运行速度,slot属性能够顺序存储以供高速查找,而不是为每一个实例分配一个字典。

-------------------------------------------------------------------------------------------------------------------------------------

Slot和通用代码

实际上。有些带有slots的实例或许根本就没有__dict__属性字典。所以在有些程序中要使用比__dict__更为存储中立的工具,比如getattr、setattr和dir内置函数。

>>> class C:
	__slots__ = ['a','b']

>>> X = C()
>>> X.a = 1
>>> X.a
1
>>> X.__dict__
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    X.__dict__
AttributeError: 'C' object has no attribute '__dict__'
>>> getattr(X,'a')
1
>>> setattr(X,'b',2)
>>> X.b
2
>>> 'a' in dir(X)
True
>>> 'b' in dir(X)
True

没有属性命名空间字典,不可能给不是slots列表中名称的实例来分配新的名称,然而,通过在__slots__中包括__dict__仍然能够容纳额外的属性,从而考虑到一个属性空间字典的须要。在这个样例中。两种机制都用到了,可是,getattr这种通用工具同意我们将它们当做单独一组属性对待:

>>> class D:
	__slots__ = ['a','b','__dict__']
	c = 3
	def __init__(self):
		self.d = 4

>>> X = D()
>>> X.d
4
>>> X.__dict__
{'d': 4}
>>> X.__slots__
['a', 'b', '__dict__']
>>> X.c
3
>>> X.a
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    X.a
AttributeError: a
>>> X.a = 1
>>> getattr(X,'a'),getattr(X,'c'),getattr(X,'d')
(1, 3, 4)

==========================================================================

类特性

有一种称为特性(property)的机制,提供还有一种方式让类定义自己主动调用的方法,来读取或赋值实例属性。

【特性和slots都是基于属性描写叙述器的新概念】

简而言之,特性是一种对象,赋值给类属性名称。特性的产生是以三种方法(获得、设置以及删除运算的处理器)以及通过文档字符串调用内置函数property。假设不论什么參数以None传递或者省略。该运算就不能支持。

特性一般都是在class语句顶层赋值【比如,name = property(...)】。这样赋值时。对类属性本身的读取(比如。obj.name),就会自己主动传给property的一个读取方法。例如以下例:

>>> class new():
	def getage(self):
		return 40
	age = property(getage,None,None,None)  # get,set,del,docs

>>> x = new()
>>> x.age
40
>>> x.name
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    x.name
AttributeError: 'new' object has no attribute 'name'

特性比传统技术执行起来更快。

比如,当我们新增属性赋值运算支持时,特性就变得更有吸引力:输入的代码更少,对我们不希望动态计算的属性进行赋值运算时,不会发生额外的方法调用。

>>> class new():
	def getage(self):
		return 40
	def setage(self,value):
		print('set age:',value)
		self._age = value
	age = property(getage,setage,None,None)

>>> x = new()
>>> x.age
40
>>> x.age = 42
set age: 42
>>> x.age
40
>>> x._age
42
>>> x.job = 'trainer'
>>> x.job
'trainer'

==========================================================================

__getattribute__和描写叙述符

__getattribute__能够让类拦截全部属性的引用。而不局限于没有定义的引用(假设__getattr__)。

除了特性和运算符重载方法,Python支持属性描写叙述符的概念——带有__get__和__set__方法的类,分配给类属性而且由实例继承,这拦截了对特定属性的读取和写入訪问。描写叙述符在某种意义上是特性的一种更加通用的形式。

关于特性、__getattribute__和描写叙述符这些高级话题将在兴许逐步介绍。

==========================================================================

静态方法

类方法通常在其第一个參数中传递一个实例对象。以充当方法调用的一个隐式主体。有时候。程序须要处理与类而不是与实例相关的数据,也就是我们须要一个类中的方法不仅不传递并且也不期待一个self实例參数。

Python通过【静态方法】的概念来支持这种目标——嵌套在一个类中的没有self參数的简单函数。

比如。如果我们想使用类属性去计算从一个类产生了多少实例。我们能够把一个计数器存储为类属性。每次创建一个新的实例的时候。构造函数都会对计数器加1。而且,有一个显示计数器值的方法。【记住,类属性是由全部实例共享的】:

>>> class Spam:
	numInstances = 0
	def __init__(self):
		Spam.numInstances += 1
	def printNumInstances():
		print('Number of instances created:',Spam.numInstances)

printNumInstances方法旨在处理类数据而不是实例数据——它是关于全部实例的,而不是某个特定的实例。因此,我们想要不必传递一个实例就能够调用它。

实际上,我们不想生成一个实例来获取实例的数目。由于这本身就会改变我们想要获取的实例的数目。

换句话说:我们想要一个无self的静态方法。

我们能够看一下測试结果:

>>> a = Spam()
>>> b = Spam()
>>> c = Spam()
>>> Spam.printNumInstances()
Number of instances created: 3
>>> a.printNumInstances()
Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    a.printNumInstances()
TypeError: printNumInstances() takes 0 positional arguments but 1 was given

能够看到,我们通过类调用无self方法执行成功。而通过实例调用无self方法出错了,由于參数不正确。通过一个实例调用方法。这个实例会自己主动传递给方法的第一个參数中,可是这个无self方法并不存在參数来接收它。

假设你可以坚持仅仅通过类调用无self方法。那么事实上你已经有了一个静态方法了。然而假设你还想通过实例调用,那么就须要採取其它设计,或者把这个方案标记为特殊的。

-------------------------------------------------------------------------------------------------------------------------------------

使用静态方法

要将这个无self方法标记为静态方法。须要调用内置函数staticmethod。例如以下:

>>> class Spam:
	numInstances = 0
	def __init__(self):
		Spam.numInstances += 1
	def printNumInstances():
		print('Number of instances created:',Spam.numInstances)
	printNumInstances = staticmethod(printNumInstances)  # staticmethod

>>> a = Spam()
>>> b = Spam()
>>> c = Spam()
>>> a.printNumInstances()
Number of instances created: 3

静态方法对于处理一个类本地的数据来说是更好的解决方式。

==========================================================================

装饰器和元类:初识

上边提到的staticmethod可能比較奇怪。所以新增了一个功能,要让这个运算变得简单。【函数装饰器】提供了一种方式,替函数明白了特定的运算模式。也就是将函数包裹了还有一层,在还有一函数的逻辑内实现。

函数装饰器变成了通用的工具:除了静态方法使用方法外。也可用于新增多种逻辑的函数。比如,能够用来记录函数调用的信息和在出错时检查传入的參数类型等

Python提供了一下内置的函数装饰器,来做一些运算,比如。标识静态方法,可是我们也能够编写自己的随意装饰器。尽管不限于使用类,但用户定义的函数装饰器通常也写成类,把原始函数和其它数据当成状态信息。

-------------------------------------------------------------------------------------------------------------------------------------

函数装饰器基础

从语法上讲,函数装饰器是它后边的函数的执行时的声明。

函数装饰器是写成一行,就在定义函数或方法的def语句之前,并且由@符号、后面跟着所谓的元函数组成:也就是管理还有一函数的函数。

比如,如今的静态方法我们能够用下述的装饰器语法编写:

class C:
	@staticmethod
	def printNumInstances():
		...

这个语法和以下的写法有同样的效果:

class C:
	def meth():
		...
	meth = staticmethod(meth)

结果就是,调用方法函数的名称。实际上是触发了它staticmethod装饰器的结果。

-------------------------------------------------------------------------------------------------------------------------------------

装饰器样例

之前介绍过,__call__运算符重载方法为类实例实现函数调用接口。

以下的程序通过这样的方法定义类。在实例中存储装饰的函数,并捕捉对最初变量名的调用。

class tracer:
    def __init__(self,func):
        self.calls = 0
        self.func = func
    def __call__(self,*args):
        self.calls += 1
        print('call %s to %s'%(self.calls,self.func.__name__))
        self.func(*args)

@tracer
def spam(a,b,c):
    print(a,b,c)

spam(1,2,3)
spam('a','b','c')
spam(4,5,6)

由于spam函数时通过tracer装饰器运行的,所以当最初的变量名spam调用时。实际上触发的是类中的__call__方法,这种方法会计算和记录该次调用,然后托付给原始的包裹的函数。

因此,此装饰器可用于包裹携带随意数目參数的不论什么函数。

结果就是新增一层逻辑至原始的spam函数。执行结果例如以下:第一行来自tracer类,第二行来自spam函数。

call 1 to spam
1 2 3
call 2 to spam
a b c
call 3 to spam
4 5 6

这里仅仅是初步了解。兴许我们将会介绍各种各种的方法来编写函数装饰器。

-------------------------------------------------------------------------------------------------------------------------------------

类装饰器和元类

类装饰器类似于函数装饰器,可是。它们在一条class语句的末尾执行,而且把一个类名又一次绑定到一个可调用对象,相同的,它们能够用来管理类,或者当随后创建实例的时候插入一个包装逻辑层来管理实例。代码结构例如以下:

def decorator(aClass):...

@decorator
class C:...

被映射为下列相当代码:

def decorator(aClass):...

class C:...
C = decorator(C)

元类是一种类似的基于类的高级工具。其用途往往与类装饰器有所重合。

它们提供了一种可选的模式。会把一个类对象的创建导向到顶级type类的一个子类。

关于装饰器和元类的内容,将在之后更加具体地介绍。

时间: 2024-08-29 04:26:36

Python——类的高级主题的相关文章

python类高级话题

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

【Python&amp;数据结构】 抽象数据类型 Python类机制和异常

这篇是<数据结构与算法Python语言描述>的笔记,但是大头在Python类机制和面向对象编程的说明上面.我也不知道该放什么分类了..总之之前也没怎么认真接触过基于类而不是独立函数的Python编程,借着本次机会仔细学习一下. 抽象数据类型 最开始的计算机语言,关注的都是如何更加有效率地计算,可以说其目的是计算层面的抽象.然而随着这个行业的不断发展,计算机不仅仅用于计算,开发也不仅只关注计算过程了,数据层面的抽象也变得同样重要.虽然计算机语言一开始就有对数据的抽象,但是那些都只是对一些最基本的

python 的一些高级编程技巧

正文: 本文展示一些高级的Python设计结构和它们的使用方法.在日常工作中,你可以根据需要选择合适的数据结构,例如对快速查找性的要求.对数据一致性的要求或是对索引的要求等,同时也可以将各种数据结构合适地结合在一起,从而生成具有逻辑性并易于理解的数据模型.Python的数据结构从句法上来看非常直观,并且提供了大量的可选操作.这篇指南尝试将大部分常用的数据结构知识放到一起,并且提供对其最佳用法的探讨. 推导式(Comprehensions) 如果你已经使用了很长时间的Python,那么你至少应该听

android开发笔记之高级主题—传感器的简单介绍

今天我们开始进入讲解android中的一些高级主题的用法,比如传感器.GPS.NFC.语音和人脸识别等. 这次来对传感器的一个简单介绍: Android平台支持三大类的传感器: 位移传感器 这些传感器测量沿三个轴线测量加速度和旋转.这类包含加速度,重力传感器,陀螺仪,和矢量传感器. 环境传感器 这些传感器测量各种环境参数,例如周围的空气温度和压力,光线,和湿度.这类包含气压,光线,和温度传感器. 位置传感器 这些传感器测量设备的物理位置.这类包含方向和磁力传感器. 这些传感器的一些是基于硬件的,

Python中的高级数据结构(转)

add by zhj: Python中的高级数据结构 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据 结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供 选择,例如Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint.本文将介绍这些数据结构的用法,看 看它

python类及其方法

python类及其方法 一.介绍 在 Python 中,面向对象编程主要有两个主题,就是类和类实例类与实例:类与实例相互关联着:类是对象的定义,而实例是"真正的实物",它存放了类中所定义的对象的具体信息. 类有这样一些的优点: 1.类对象是多态的:也就是多种形态,这意味着我们可以对不同的类对象使用同样的操作方法,而不需要额外写代码. 2.类的封装:封装之后,可以直接调用类的对象,来操作内部的一些类方法,不需要让使用者看到代码工作的细节. 3.类的继承:类可以从其它类或者元类中继承它们的

Python之路,Day8 - Python基础 面向对象高级进阶与socket基础

类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份. 一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 class Province: # 静态字段 country = '中国'def __init__(self, name): #

python类:描述器Descriptors和元类MetaClasses

http://blog.csdn.net/pipisorry/article/details/50444769 描述器(Descriptors) 描述器决定了对象属性是如何被访问的.描述器的作用是定制当你想引用一个属性时所发生的操作. 构建描述器的方法是至少定义以下三个方法中的一个.需要注意,下文中的instance是包含被访问属性的对象实例,而owner则是被描述器修辞的类. __get__(self, instance, owner) – 这个方法是当属性被通过(value = obj.at

Python中的高级数据结构详解

这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考下 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供选择