• python学习第十七天 --定制类


    何为定制类?

    Python的class允许定义许多特殊方法,可以让我们非常方便地生成特定的类。在类中应用或者重写python的特殊方法,得到的类,就是定制类。

    大家都知道print的用法。见下面例子

    >>> lst = [2,3,4]
    >>> print lst
    [2, 3, 4]
    >>> class Animal(object):
        pass
    
    >>> a = Animal()
    >>> print a
    <__main__.Animal object at 0x01E6E990>

    为什么print都能识别出lst和p的数据类型呢?

    当我们执行如下代码的时候,就知道为什么了?

    >>> print lst.__str__
    <method-wrapper '__str__' of list object at 0x01E641E8>
    >>> print a.__str__
    <method-wrapper '__str__' of Animal object at 0x01E6E990>

    __str__特殊方法,能识别出每一个数据类型。如果希望类的实例print a 打印出 ‘object of Animal class’.怎么办?重新定义__str__方法。

    >>> class Animal(object):
        def __str__(self):
            return 'object of Animal class'
    
        
    >>> a = Animal()
    >>> print a
    object of Animal class

    但是有时候发现直接敲

    >>> a
    <__main__.Animal object at 0x01E6E990>

    __str__不会被调用。因为当直接敲a这行代码的时候,直接调用的并不是__str__.而是__repr__.

    >>> class Animal(object):
        def __str__(self):
            return 'object of Animal class'
        __repr__ = __str__ //偷懒一下
    
        
    >>> a = Animal()
    >>> a
    object of Animal class

    python的特殊方法很多,这里就不做一一介绍。下面主要介绍 __slots__,__call__,@property用法。

    __slots__

    python是一个动态语言,任何实例可以再运行期间都能动态添加实例的属性。但是有时候,想限制实例的添加属性,就使用__slot__方法。见下面例子:

    >>> class Person(object):
        __slots__ = ('name','age')//限制只有name和age的属性
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
            
    >>> p = Person('zhangsan',25)
    >>> p.age
    25
    >>> p.name
    'zhangsan'
    >>> p.gender ='man'//直接动态赋属性gender,会出现错误
    
    Traceback (most recent call last):
      File "<pyshell#42>", line 1, in <module>
        p.gender ='man'
    AttributeError: 'Person' object has no attribute 'gender'

    __slot__目的是限制当前类所能拥有的属性。所以在继承的环境下,子类不受影响。

    >>> class Student(Person):
        pass
    
    >>> s = Student('zhangsan',26)
    >>> s.age
    26
    >>> s.name
    'zhangsan'
    >>> s.gender = 'man'//可以动态添加属性
    >>> s.gender
    'man'

    所以子类Student如果想自己限制添加属性的话,也要通过__slots__来控制。

    __call__

    一个类的实例可以变成一个可调用的对象,只需要实现一个特殊的方法__call__就可以了。

    接下来我们把Student类变成一个可调用的对象:

    >>> class Student(Person):
        def __init__(self,name,score):
            self.name = name
            self.score = score
    
            
    >>> class Student(Person):
        def __init__(self,name,score):
            self.name = name
            self.score = score
        def __call__(self,age):
            print 'my name is %s'% self.name
            print 'my age is %d'% age
    
            
    >>> s = Student('lixi',89)
    >>> s(25)
    my name is lixi
    my age is 25

    有时候你会发现s(25)乍一眼感觉不出来是一个函数还是对象的实例。python语言函数和对象的实例不是区分的很明显。

    @property

    上述的class Student中,当修改s实例的score值时,

    >>> s.score = 89
    >>> s.score = 9999

    但是这样无法检查s实例的分数有效性。目前只能这样做:

    >>> class Student(object):
        def __init__(self,name,score):
            self.name = name
            self.__score = score
        def set_score(self,score):
            if score <0 or score >100:
                raise ValueError('invalid score')
            self.__score = score
        def get_score(self):
            return self.__score
    
    >>> s = Student('wangwu',89)
    >>> s.set_score(89)
    >>> s.set_score(9999) //非法值,ValueError
    
    Traceback (most recent call last):
      File "<pyshell#75>", line 1, in <module>
        s.set_score(9999)
      File "<pyshell#71>", line 7, in set_score
        raise ValueError('invalid score')
    ValueError: invalid score

    有时候觉得写s.set_score和s.get_score没有直接写s.score那么直接。有没有其他办法?既能直接的s.score又能检查score的有效性?python提供@property高阶函数这样功能需求的装饰器。

    >>> class Student(object):
        def __init__(self,name,score):
            self.name = name
            self.__score = score
        @property
        def score(self):
            return self.__score
        
        @score.setter
        def score(self,score):
            if score <0 or score >100:
                raise ValueError('invalid score')
            self.__score = score
    
    >>> s = Student('liunx',98)
    >>> s.score = 89
    >>> s.score = 9999
    
    Traceback (most recent call last):
      File "<pyshell#82>", line 1, in <module>
        s.score = 9999
      File "<pyshell#79>", line 12, in score
        raise ValueError('invalid score')
    ValueError: invalid score

    小结:

    特殊方法:

    1.任何数据实例都有特殊方法

    2.特殊方法定义在class中

    3.不需要直接调用

    4.python的某些方法或者函数会直接调用数据实例的特殊方法

    实现特殊方法:

    1.重新编写用到的特殊方法

    2.如果重新一些特殊方法,有些关联的特殊方法也要一并实现。例如:__setattr__,__getattr__,__delattr__

  • 相关阅读:
    非域账户如何连接SQL Server Analysis Service
    Ranet.UILibrary.OLAP
    给Silverlight项目Ranet.UILibrary.OLAP添加客户端调试功能
    编译及安装QCA类库
    关于软件生态环境
    Windows7中操作mysql数据库
    介绍自己
    VS2008技巧收集
    .NET开发不可错过的25款必备工具
    如何做搜索引擎优化(SEO)
  • 原文地址:https://www.cnblogs.com/nx520zj/p/5757807.html
Copyright © 2020-2023  润新知