python类高级话题

1、变量名压缩

                class 语句内开头 有两个下划线,但结尾没有两个下划线的变量名会自动扩张,从而包含所在类的名称。例如:象spam类内__x这样的变量名会自动变成 _spam__x.原始的变量名会在开头家一个下划线,然后是再加上所在类的类名。这一规则适用了每个开头有两个下划线 的变量名,包括方法名称和实例属性名称。(例如:在spam类内,self.__x实例属性会变成self._spam__x)

2、方法是对象:绑定或无绑定

                无绑定类方法对象: 无self

                                通过对类进行点号运算从而获取函数的属性,会传回无绑定方法对象,调用该方法时,必须提供实例对象作为第一个参数,在python3.0中,一个无绑定方法和一个简单函数相同。可以通过类名来调用,在python2.6中,他是一个特殊的类型,并且不提供一个实例就无法调用

                绑定实例方法对象: self+函数对

                                通过对实例进行全运算,从而获取类的汗水属性,会传回绑定方法对象。python在绑定方法对象中自动实现实例和函数的打包,所以不用传递实例去调用该方法。

                例如:

                class Spam:

                                def doit(self,message):

                                                print(message)

               

                在下面代码中,会传回绑定方法对象,把实例(object1)和方法函数(spam.doit)打包起来。我们可以把这个绑定方法赋值给另外一个变量。然后像函数那样进行调用。

                object1 = spam()

                x = object1.doit

                x('hello world')

                另一方面,如果对类进行点号运算来获得doit就会获得无绑定方法对象。也就是函数对象的引用值。要调用这个类方法时,必须传入实例作为最左侧参数

                例如:

                object2 = Spam()

                t = Spam.doit

                t(object2,'howdy')

                扩展一下:如果我们引用的self属性是引用类中的函数,那么相同的规则也适用于类的方法。self.method表达式是邦定方法,因为self是实例对象。

                例如:

                class C:

                def m1(self,n):

                                print('m1=',n)

                def m2(self,t):

                                x = self.m1  #这里是通过实例和方法打包,是绑定方法。

                                x(t)#在这里调用绑定方法不需要传入实例

                                print('m2=',t)

                c = C()

                c.m2(88)

                print('#'*8)

                C.m2(c,77)

                print('-'*8)

                class B:

                                def m1(self,n):

                                                print('m1=',n)

                                def m2(self,t):

                                                x = B.m1  #这里通过类来获取类中的函数,是无绑定方法对象

                                                x(self,t)#这里使用时需要传入一个类对象。

                                                print('m2=',t)

                b = B()

                B.m2(b,99)

                print('@'*8)

                b.m2(66)

                #输出结果:

                m1= 88

                m2= 88

                ########

                m1= 77

                m2= 77

                --------

                m1= 99

                m2= 99

                @@@@@@@@

                m1= 66

                m2= 66

3、在python3.0中无绑定方法是函数

                在python3.0中已经删除"无绑定方法"的概念,但是还是可以使用。在上面介绍的绑定方法,在python3.0中只当作一个简单函数来使用。简单函数不期待传递给他一个实例,非简单函数期待传递一个实例。

                此外:在python3.0中不使用一个实例而调用一个方法没有问题,只要这个方法不期待一个实例,并且你通过类调用它而不是通过一个实例调用它。也就是说,只有对通过实例调用,python3.0才会向方法传递一个实例。当通过一个类调用的时候,只有在方法期待一个实例的时候,才必须手动传递一个实例。

                class Selfless:

                                def __init__(self,data):

                                                self.data = data

                                def selfless(arg1,arg2):

                                                return arg1+arg2

                                def normal(self,arg1,arg2):

                                                return self.data+arg1+arg2

                x = Selfless(2)

                print(x.normal(3,4))

                print('-'*8)

                print(Selfless.normal(x,3,4))

                print('-'*8)

                print(Selfless.selfless(3,4))  #在python3.0中可以通过一个类去调用这个类的普通方法,但是在python2.6中不行,会抱错。

                print('-'*8)

                #print(x.selfess(3,4))  不能通过实例去调用一个类的普通方法

4、多重集成

                在传统类中(默认的类,直到python3.0),属性搜索处理对所有路径深度优先 ,直到继承树的顶端,然后从左到右

                在新式类(以及python.30的所有类中)属性搜索处理沿着树层级,以及更宽广优先的方式。

                例如:使用__dict__列出实例属性

                class  Listinstance:

                                '''

                                Mix-in class that provides a formatted print() or str() of instance of via inheritance of __str__, coded here:displays instance attrs only;self is the instance of lowest class;

                                uses __x names to avoid clashing with client's attrs

                                '''

                                def __str__(self):

                                                return '<Instance of %s, adderss %s:\n%s>'%(

                                                self.__class__.__name__,#每个实例都有一个内置的__class__属性,它引用创建 自己的类,并且每一个类都有一个__name__属性。他引用头部的名称。

                                                id(self),  #返回该对象的内存地址

                                                self.__attrnames()

                                                )

                                def __attrnames(self):

                                                result = ''

                                                for attr in sorted(self.__dict__):

                                                                result+='\tname %s=%s\n'%(attr,self.__dict__[attr])

                                                return result

                s = spam(12)

                print(s)

                #输出:

                                <Instance of spam, adderss 3073187084:

                                                name data=12

                                >

                例如:使用dir列出继承的所有属性

                                class ListInherited:

                                                '''

                                                Use dir() to collect both instance attrs and names

                                                inherited from its classes; python3.0 shows more

                                                names than 2.6 because of the implied object supperclass

                                                in the new-style class model; getattr() fetches inherited

                                                names not in self.__dict__;use __str__,not __repr__

                                                or else this loops when printing bound methods

                                                '''

                                                def __str__(self):

                                                                return '<Instance of %s, address %s:\n%s>'(self.__class_.__name,

                                                                id(self),

                                                                self.__attrnames())

                                                def __attrnames(self):

                                                                result = ''

                                                                for attr in dir(self):

                                                                                if attr[:2] == '__' and attr[-2:] == '__':

                                                                                                result+='\tname %s = <>'%attr

                                                                                else:

                                                                                                result += '\tname %s=%s\n'%(attr,getattr(self,attr))

                                                                return result

                例如:列出类树中的每个对象的属性

                class ListTree:

                                '''

                                Mix-in that returns an __str__ trace of the entire class

                                tree and all its objects'attrs at and above self;

                                run by print(),str() returns constructed string;

                                uses __x attr names to void impacting clients;

                                uses generator expr to recurse to superclasses;

                                uses str.format() to make substituion clear

                                '''

                                def __str__(self):

                                                self.__visited = {}

                                                return '<Instance of {0}, address {1}:\n{2}{3}'.format(

                                                self.__class__.__name__,

                                                id(self),

                                                self.__attrnames(self,0),

                                                self.__listclass(self.__class_,4)

                                                )

                                def __listclass(self,aClass,indent):

                                                dots = '.'*indent

                                                if aClass in self.__visited:

                                                                return '\n{0}<Class {1}:,address {2}:(see above)>\n'.format(

                                                                dots,

                                                                aClass.__name,

                                                                id(aClass)

                                                                )

                                                else:

                                                                self.__visited[aClass]=True

                                                                genabove = (self.__listclass(c,indent+4) for c in aClass.__base__)

                                                                return '\n{0}<Class {1} , address {2}:\n{3}{4}{5}>\n'.format(

                                                                dots,

                                                                aClass.__name__,

                                                                id(aClass),

                                                                self.__attrnames(aClass,indent),

                                                                ''.join(genabove),

                                                                dots

                                                                )

                                def __attrnames(self,obj,indent):

                                                spaces = ' ' * (indent+4)

                                                result = ''

                                                for attr in sorted(obj.__dict__):

                                                                if attr.startwith('__') and attr.endwith('__'):

                                                                                resutl +=spaces +'{0}=<>\n'.format(attr)

                                                                else:

                                                                                result ++space+'{0}={1}\n'.format(attr,getattr(obj,attr))

                                                return result

4、新式类

                对于python3.0来说,所有类都是我们所谓的”新式类“,不管他们是否显示继承object.所有类都继承自object.不管显式还是隐式,所有对象都是object的实例

                在python2.6及其以前版本,类必须继承自类看作是新式”object,并且获得新式类的特性。

5、新式类的变化

                1)类和类型合并

                                类现在就是类型,并且类型现在就是类,实际上,这二者基本上是同义词。type(I)内置函数返回一个创建这个实例I的类。而不是一个通用实例类型,并且,通常是和I.__class__相同。此外,雷氏type类的实例,type可能子类化

6、__slots__

                如果一个字类继承一个没有__slots__的超类,那么超类的__dict__属性总是可以访问的,使得字类的__slots__没有意义

                如果一个超类定义了一个与超类相同的slots名称,超类slots定义的名称只有通过从直接超类获取其描述符才能访问

                由于一个超类__slots__声明的含义受到它出现其中类的限制,所以一个字类将有一个__dict__除非他也声明了一个__slots__

                通常从列出实例属性这方面来看,多数类的slots可能需要手动类树爬升、dir用法或者把slot名称当作不同的名称领域的政策

7、特性

                适用条件是这个类必须继承object

                class classic:

                                def getx(self)

                                                return self.__x

                                def setx(self,data):

                                                self.__x =data

                                def delx(self)

                                                self.__x = None

                                x = property(getx,setx,delx,None)

8、__getattribute__方法只适用于新式类,可以让类拦截所有属性的引用,而不是局限于未定义的引用

9、静态方法和类方法

                不用一个实例就可以调用 :静态方法

                传递一个类而不是一个实例:类方法

10、静态方法和类方法使用实例

                静态方法:      

                class Spam:

                                numInstances = 0

                                def __init__(self):

                                                Spam.numInstances +=1

                                def printNumInstance():

                                                print("Number of instance:",Spam.numInstances)

                                printNumInstance = staticmethod(printNumInstance)

                a = Spam()

                b = Spam()

                c = Spam()

                Spam.printNumInstance()

                a.printNumInstance()

                继承:

                class Sub(Spam):

                                def printNumInstance():

                                                print('extra stauff...')

                                                Spam.printNumInstance()

                                printNumInstance = staticmethod(printNumInstance)

                a = Sub()

                b = Sub()

                a.printNumInstance()

                Sub.printNumInstance()

                Spam.printNumInstance()

               

                类方法

                class Spam:

                                numInstances = 0

                                def __init__(self):

                                                Spam.numInstances +=1

                                def printNumInstance(cls):

                                                print("Num of instnace:", cls.numInstances)

                                printNumInstance = classmethod(printNumInstance)

                a,b = Spam(),Spam()

                a.printNumInstance()

                Spam.printNumInstance()

                继承方法同静态方法相同

11、装饰器和元类

                例如:

                class Spam:

                                numInstances = 0

                                def __init__(self):

                                                Spam.numInstances +=1

                                @staticmethod

                                def printNumInstance():

                                                print("Number of instance:",Spam.numInstances)

                a = Spam()

                b = Spam()

                c = Spam()

                Spam.printNumInstance()

                a.printNumInstance()

  

posted @ 2014-05-05 20:25  再不奋斗就会被淘汰  阅读(370)  评论(0编辑  收藏  举报