Python:class类

来源:互联网 发布:小语网络加速器 编辑:程序博客网 时间:2024/06/08 18:17

类及其类属性

1.属性就是属于另一个对象的数据或者函数元素,可以通过我们熟悉的句点属性标示法来访问。
2.类属性仅与其被定义的类相绑定,由于实例对象在日常的面向对象编程中用得最多,实例数据属性是你将会一直用到的主要数据属性。
类数据属性仅当需要更加“静态”数据类型时才变得有用,他和任何实例都无关。

类的数据属性

这种属性是一种静态变量,表示这些数据是与他们所属的类对象绑定的,不依赖于任何类实例。

>>>>>> class my(object):...     foo=100  #类属性...>>> print my.foo100>>> my.foo=my.foo+1>>> my.foo101>>>

以上代码没有出现任何实例的引用

方法

方法其实就是类中定义的函数,他是属于类属性的,并不属于实例属性。虽然他是类属性,但是并不能直接通过类来调用。

>>> class my(object):...     def my_method(self):...         pass...>>> c=my()>>> c.my_method()  #通过实例调用>>> my.my_method()  #通过类直接调用这个方法Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: unbound method my_method() must be called with my instance as first argument (got nothing instead)>>>

为什么会出错,明明方法也是类属性,接下来解释这个问题
绑定(绑定以及非绑定方法)为了与oop惯例保持一致,python严格要求,没有实例,方法是不能被调用的,这种限制即Python所描述的绑定概念,方法必须与实例绑定才能被直接被调用。 非绑定方法可能可以被调用,但实例对象一定要明确给出,才能确保调用成功。

dir

要知道一个类有哪些属性,有两种方法,最简单的是使用dir()内建函数,另为一个就是通过访问类的字典属性__dict__,这是所有类都具备的特殊属性之一。

>>> class myclass(object):...     myversion=1.0...     def show(self):...         print myclass.myversion...>>> dir(myclass)['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'myversion', 'show']>>> myclass.__dict__dict_proxy({'__module__': '__main__', 'show': <function show at 0x0000000002D51EB8>, '__dict__': <attribute '__dict__' of 'myclass' objects>, 'myversion': 1.0,'__weakref__': <attribute '__weakref__' of 'myclass' objects>, '__doc__': None})>>>

从上面的代码可以看出,dir()返回的仅是对象的属性的一个名字列表,可以打印类属性,还可以打印所有的实例属性,而__dict__返回的是一个字典,他的键是属性名,键值是相应的属性对象的数据值。

特殊的类属性

C.__name__      类C的名字(字符串)C.__doc__       类C的文档字符串C.__bases__     类C的所有父类构成的元组C.__dict__      类C的属性C.__module__    类C定义所在的模块C.__class__     实例C对应的类(仅新式类中)

实例

如果说类是一种数据结构定义的类型,那么实例则声明了一个这种类型的变量。

__init__()“构造器”方法

当类被调用的时候,实例化的第一步就是创建实例对象,一旦对象创建了,Python检查是否实现了__init__()方法,默认情况下,如果没有定义(或者覆盖)特殊方法__init__(),对实例不会施加任何特别操作,任何所需要的特定操作,都需要程序员实现__init__(),覆盖它的默认行为。
如果__init__()已经被实现 ,那么它将被调用,实例对象作为第一个参数(self)被传递进去,调用类的时候,传进去的任何参数都交给了__init__()

__new__()“构造器”方法

__init__()方法相比,__new__()方法更像一个真正的构造器,python可以对内建类型进行派生,因此,需要一种途径来实例化不可变对象,比如派生字符串,数字等
__new__()相比与__init__()方法,__new__()必须返回一个合法的实例,这样解释器在调用__init__()时,就可以把这个实例作为self传给他。简单的说就是new调用了init

__call__

有了这个特殊方法,就可以像函数一样调用实例了

class Test(object):    def __init__(self,name):        self.name=name    def __call__(self,age):        self.age=age        return "%s is %s"%(self.name,self.age)t=Test('cmustard')print t(23)  #调用实例"cmustard is 23"

实例属性

实例仅拥有数据属性(方法严格来说是类属性),当一个实例被释放后,他的属性同时也被清除了。
构造器是最早设置实例属性的地方,一旦__init__()执行完毕,返回实例对象,即完成了实例化过程

查看实例属性

>>> class my(object):...     pass...>>> c=my()>>> c.foo='cmustard'>>> c.bar=12312>>> dir(c)  #所有属性,包括类属性和实例属性['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo']>>> c.__dict__  #返回实例对象构成的字典{'foo': 'cmustard', 'bar': 12312}>>>

实例属性和类属性比较

类属性仅是与类相关的数据值,和实例属性不同,类属性和实例属性无关。类和实例都是名字空间,类是类属性的名字空间,实例则是实例属性的。我们可以采用类来访问类属性,如果实例没有同名的属性的话,你也可以用实例来访问。

>>> class my(object):...     myversion=1...     def __init__(self,name):...         self.name=name...>>> class my(object):...     myversion=1...     def __init__(self,name):...         self.name=name...     def show(self,age):...         print "name is %s age is %s"%(self.name,age)...>>> c=my('cmustard')>>> c.name   #访问实例属性'cmustard'>>> c.myversion  #访问myversion,实例属性中没有,于是访问的是类属性中的变量1>>> c2=my("abner")>>> c2.show(22)  #访问方法name is abner age is 22>>> c.show(18)name is cmustard age is 18>>> c2.myversion  #访问myversion,实例属性中没有,于是访问的是类属性中的变量1>>> my.myversion  #通过类直接访问类属性1>>> c.myversion=100 #在实例c中修改myversion,相当与在实例c中动态添加了一个新的属性>>> c.myversion100>>> c2.myversion  #在实例c2中myversion的值依然没有改变1>>> my.myversion=150 #通过类直接修改myversion的值>>> c.myversion  #实例c中的值没有发生改变,因为实例c中已经有一个名叫myversion的变量了100>>> c2.myversion #实例c2中值随着类的改变而改变,因为实例c2中没有myversion这个变量,只能访问类属性中的变量150 >>> my.myversion150>>>

绑定和方法调用

方法只有在所属的类拥有实例的时候才能被调用,当存在一个实例的时候,方法才被认为是绑定到了那个实例,没有实例时方法就是未绑定的
self是什么:self变量用于在类实例方法中引用方法所绑定的实例,因为在方法的实例在任何方法调用中总是作为一个参数传递的,self被选中用来代替实例。

调用绑定方法

就是用实例调用这个方法

调用非绑定方法

调用非绑定方法并不经常用到,主要应用场景:你在派生一个子类 ,而且你要覆盖父类的方法,这时你需要调用哪个父类中想要覆盖的构造方法。

class Foo(object):    def __init__(self,name,sex,age):        self.name=name        self.sex=sex        self.age=age    def show(self):        print "name is %s,sex is %s"%(self.name,self.sex)class Bar(Foo):    def __init__(self,name,sex,age,id,salary):        super(Bar,self).__init__(name,sex,age) #这就是在调用父类非绑定方法        #或者Foo.__init__(self,name,sex,age)  现在不用了        self.id=id        self.salary=salary    def info(self):        print "name is %s salary is %s"%(self.name,self.salary)>>> f=Bar('cmustard','F',22,123123,1000)>>> f.show()name is cmustard,sex is F>>> f.info()name is cmustard salary is 1000>>>

静态方法和类方法

静态方法中默认是不能访问类变量和实例变量。
类方法不能访问实例变量

class TestS(object):    @staticmethod    def foo():        print "calling static method foo()"class TestC(object):    @classmethod    def foo(cls):        print "calling class method foo()"        print "foo() is part of class",cls.__name__>>> s=TestS()>>> s.foo()calling static method foo()>>> TestS.foo()  #直接调用静态方法calling static method foo()>>>>>>>>> c=TestC()>>> TestC().foo()calling class method foo()foo() is part of class TestC>>> c.foo()calling class method foo()foo() is part of class TestC>>>

property属性

@property装饰器是把方法转变成属性访问,简单来说就是实例访问这个方法的时候,不需要加括号

#coding:utf-8class TestP(object):    def __init__(self,name):        self.name=name        self.num=0    @property    def total(self):        return "is %s"%self.num    @total.setter  #设置属性的值    def total(self,num):        self.num=num    @total.deleter #删除这个属性    def total(self):        del self.nump=TestP('cmustard')print p.total  #is 0#怎么给他赋值呢  需要setter装饰器p.total=10print p.total #is 10#怎么删除这个属性del p.totalprint p.total  #'TestP' object has no attribute 'num'

这个有什么作用呢,我们还是可以直接改变num的值呀。。

p.num=100  print p.num  #100

这时我们需要引用私有变量

class TestP(object):    def __init__(self,name):        self.name=name        self.__num=0  #设置了一个私有变量    @property    def total(self):        return "is %s"%self.__num    @total.setter  #设置属性的值    def total(self,num):        self.__num=num    @total.deleter #删除这个属性    def total(self):        del self.__nump=TestP('cmustard')p.total=100print p.total  #is 100#倘若直接修改呢p.__num=130print p.__num #130print p.__dict__  #{'_TestP__num': 100, 'num': 120, 'name': 'cmustard', '__num': 130},这里只是在实例属性中添加了一个新的变量print p.total  #is 100  还是没有改变#特殊情况p._TestP__num=110print p.total #is 110  这就改变了,不过我们一般不会这么用的
0 0
原创粉丝点击