zoukankan      html  css  js  c++  java
  • python之类

    1. 类属性

    特殊的类属性

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

     

     

    2. 实例属性

    实例仅有两个特殊属性

    __class__ 实例的类
    __dict__ 实例的属性

    >>> class C(object):
        pass
        
    >>> c = C()
    >>> c.foo = 1
    >>> c.bar = 2
    >>> c.__dict__
    {'foo': 1, 'bar': 2}
    >>> c.__class__
    <class '__main__.C'>

    使用__slots__限制实例添加属性

    class Student(object):
        __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
    
    >>> s = Student() # 创建新的实例
    >>> s.name = 'Michael' # 绑定属性'name'
    >>> s.age = 25 # 绑定属性'age'
    >>> s.score = 99 # 绑定属性'score'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'score'

    实例属性 vs 类属性

    类和实例都是名称空间。类是类属性的名称空间,实例则是实例属性的。可采用类来访问类属性,如果实例没有同名属性,则也可用实例来访问。
    但修改类属性要使用类名,而不是实例名

    >>> class C(object):
        version = 1.0
     
    >>> c = C()
    >>> C.version
    1.0
    >>> c.version
    1.0
    >>> c.version += 0.1    # 创建了一个实例属性version, 覆盖了同名类属性
    >>> c.version
    1.1
    >>> C.version
    1.0
    >>> C.version += 0.1
    >>> C.verison
    1.1
    >>> c.version
    1.1      # 类属性的修改会影响到所有实例

    补充:Python 没有提供任何内部机制来跟踪一个类有多少个实例被创建了, 但可以通过一个类属性来记录实例的个数。

    class Hello(object):
        count = 0
    
        def __init__(self):
            Hello.count += 1
    
        def __del__(self):
            Hello.count -= 1
    
            
    >>> a = Hello()
    >>> b = Hello()
    >>> Hello.count
    2
    >>> del a
    >>> Hello.count
    1

    3. classmethod 、 staticmethod 、@property 

    @property 

    class Student(object):  
    #birth是可读写属性(多定义了一个setter的装饰器),而age就是一个只读属性  
        @property  
        def birth(self):  
            return self._birth  
     
        @birth.setter  
        def birth(self, value):  
            self._birth = value  
     
        @property  
        def age(self):  
            return 2014 - self._birth  
      
    ---------------------------------      
    >>>s = Student()  
    >>>s.birth = 2000  
    >>>s.birth  
    2000  
    >>>s.age
    14  

    @classmethod 和 @staticmethod

    @classmethod 和 @staticmethod都可以让直接以类方式访问某个内置函数。但@classmethod要求的第一个参数为cls(即类自身,而不是实例自身(实例自身用self))
    @classmethod 的函数可以在类中继承,而@staticmethod不行。

    class Date(object):  
        def __init__(self, month, day, year):  
            self.month = month  
            self.day   = day  
            self.year  = year  
     
        @staticmethod  
        def millenium_1(month, day):  
            return Date(month, day, 2000)  
     
        @classmethod  
        def millenium_2(cls, month, day):  
            #cls is an object that holds class itself  
            return cls(month, day, 2000)  
      
    class DateTime(Date):  
        def display(self):  
            return "{0}-{1}-{2} - 00:00:00PM".format(self.month, self.day, self.year)  
      
    new_year = Date(1, 1, 2013)               
    millenium_new_year_1 = Date.millenium_1(1, 1)  
    millenium_new_year_2 = Date.millenium_2(1, 1)  
    isinstance(new_year, Date) # True  
    isinstance(millenium_new_year_1, Date) # True
    isinstance(millenium_new_year_2, Date) # True  
      
    datetime1 = DateTime(10, 10, 1990)  
    datetime2 = DateTime.millenium_1(10, 10)  
    datetime3 = DateTime.millenium_2(10, 10)  
    isinstance(datetime1, DateTime) # True  
    isinstance(datetime2, DateTime) # False  
    isinstance(datetime2, DateTime) # True

    4. 类的继承

    一般没有什么可以继承时,继承object(采用新式类)。

    如果有同名属性,则子类的属性会覆盖基类的属性(__doc__属性不会继承),但可以用super显示调用基类属性。

    >>> class P(object):
        def __init__(self):
            print "It's P"
            
    >>> class C(P):
        def __init__(self):
            print "It's C"
            
    >>> c = C()
    It's C
    >>> class C(P):
        def __init__(self):
            super(C, self).__init__()
            print "It's C"
            
    >>> c = C()
    It's P
    It's C

    4.1 从标准类型派生

    4.2 多重继承

    class P1(object): # parent class 1 父类1
        def foo(self):
            print 'called P1-foo()'
    
    class P2(object): # parent class 2 父类2
        def foo(self):
            print 'called P2-foo()'
    
    class C1(P1, P2): # child 1 der. from P1, P2 #子类1,从P1,P2派生
        pass
    
    class C2(P1, P2): # child 2 der. from P1, P2 #子类2,从P1,P2派生
        def bar(self):
            print 'called C2-bar()'
    
    class GC(C1, C2): # define grandchild class #定义子孙类
        pass # derived from C1 and C2 #从C1,C2派生
    
    # 新式类采用广度优先的继承方式
    >>> gc = GC()
    >>> gc.foo() # GC ==> C1 ==> C2 ==> P1
    called P1-foo()
    >>> gc.bar() # GC ==> C1 ==> C2
    called C2-bar()
    
    # 但如果是经典类, 即P1,P2不是继承object, 则采用深度优先,从左至右的继承方式
    >>> gc = GC()
    >>> gc.foo() # GC ==> C1 ==> P1
    called P1-foo()
    >>> gc.bar() # GC ==> C1 ==> P1 ==> P2
    called P2-bar()

    5. 类、实例和其他对象的内建函数

    issubclass()
    isinstance()
    hasattr()、getattr()、setattr()、delattr()
    dir()
    super()
    vars() # 同__dict__

     

    6. 定制类

    http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013946328809098c1be08a2c7e4319bd60269f62be04fa000

    https://docs.python.org/2/reference/datamodel.html#special-method-names

    6.1  __str__、 __repr__

    class Student(object):
        def __init__(self, name):
            self.name = name
        def __str__(self):
            return 'Student object (name=%s)' % self.name
        __repr__ = __str__
    
    >>>print Student('David')
    >>>Student('David')
    ----------------
    Student object (name=David)    #__str__
    Student object (name=David)    #__repr__

     

    6.2 __getattr__

    class Student(object):
    
        def __init__(self, name):
            self.name = 'Michael'
    
        def __getattr__(self, attr):
            if attr=='score':
                return 99
    
    >>>student = Student('David')
    >>>student.name
    >>>student.score
    >>>print student.grade
    ---------------
    'David'
    99
    None    #可以让class只响应特定的几个属性(通过抛出AttributeError的错误)

     

    6.3 __iter__

    如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

    class Fib(object):
        def __init__(self):
            self.a, self.b = 0, 1 # 初始化两个计数器a,b
    
        def __iter__(self):
            return self # 实例本身就是迭代对象,故返回自己
    
        def next(self):
            self.a, self.b = self.b, self.a + self.b # 计算下一个值
            if self.a > 1000: # 退出循环的条件
                raise StopIteration();
            return self.a # 返回下一个值
    
    >>> for n in Fib():
    ...     print n,
    ------------------------
    1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 

     

    6.4 __getitem__

    class Fib(object):
        def __getitem__(self, n):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
    -------------------------
    >>> f = Fib()
    >>> f[0]
    1
    >>> f[1]
    1
    >>> f[2]
    2
    >>> f[10]
    89
    >>> f[100]
    573147844013817084101

     

    6.5 __call__
    而且通过callable()函数,我们就可以判断一个对象是否是“可调用”对象

    class Student(object):
        def __init__(self, name):
            self.name = name
    
        def __call__(self):
            print('My name is %s.' % self.name)
    
    >>>student = Student('Daivd')
    >>>student()
    ---------------------
    My name is David.

     

    7. 私有化

    名称前的单下划线

    名称前的单下划线,用于指定该名称属性为“私有”。这有点类似于惯例,为了使其他人(或你自己)使用这些代码时将会知道以“_”开头的名称只供内部使用。正如Python文档中所述:

    以下划线“_”为前缀的名称(如_spam)应该被视为API中非公开的部分(不管是函数、方法还是数据成员)。此时,应该将它们看作是一种实现细节,在修改它们时无需对外部通知。

    名称前的双下划线

    名称(具体为一个方法名)前双下划线(__)的用法并不是一种惯例,对解释器来说它有特定的意义。

    Python中的这种用法是为了避免与子类定义的名称冲突。Python文档指出,“__spam”这种形式(至少两个前导下划线,最多一个后续下划线)的任何标识符将会被“_classname__spam”这种形式原文取代,在这里“classname”是去掉前导下划线的当前类名。

    >>> class A(object): 
    ... def _internal_use(self): 
    ...     pass
    ... def __method_name(self): 
    ...     pass
    ... 
    >>> dir(A()) 
    ['_A__method_name', ..., '_internal_use']
    
    >>> class B(A): 
    ... def __method_name(self): 
    ... pass
    ... 
    >>> dir(B()) 
    ['_A__method_name', '_B__method_name', ..., '_internal_use']

    8. 元类

    metaclasses are what create these objects.They are the classes' classes.

    http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

    任何子类可以通过metaclass扫描映射关系,并存储到基类的class中。(往往用于那些需要动态创建类的场合,如orm)

    type

    type is the metaclass Python uses to create all classes behind the scenes.

    age = 35
    age.__class__
    #<type 'int'>
    age.__class__.__class__
    #<type 'type'>

    自定义metaclass

    The main purpose of a metaclass is to change the class automatically, when it's created. You usually do this for APIs, where you want to create classes matching the current context.  A typical example of this is the Django ORM.

    当用户定义一个类时,Python解释器首先在当前类的定义中查找__metaclass__,如果没有找到,就继续在父类中查找,找到了,就使用父类中定义的__metaclass__来创建,也就是说,metaclass可以隐式地继承到子类,但子类自己却感觉不到。

    class UpperAttrMetaclass(type): 
        # __new__ is the method called before __init__
        # it's the method that creates the object and returns it
        # while __init__ just initializes the object passed as parameter
        # you rarely use __new__, except when you want to control how the objectis created.
        # here the created object is the class, and we want to customize it, so we override __new__
        # you can do some stuff in __init__ too if you wish
        # some advanced use involves overriding __call__ as well
        def __new__(cls, clsname, bases, dct):
            uppercase_attr = {}
            for name, val in dct.items():
                if not name.startswith('__'):
                    uppercase_attr[name.upper()] = val
                else:
                    uppercase_attr[name] = val
    
            return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)

    __new__接收到的参数依次是:

    1. 当前准备创建的类的对象

    2. 类的名字

    3. 类继承的父类集合

    4. 类的方法集合

     

     2015-06-01

  • 相关阅读:
    AJAX
    Django(cookie和session)
    Django(分页)
    跨站请求伪造和csrf_token使用
    Django(ORM查询联系题)
    Django(ORM查询2)
    Django(ORM查询1)
    Django(ORM常用字段)
    复习
    第二次作业:卷积神经网络 part2
  • 原文地址:https://www.cnblogs.com/whuyt/p/4538243.html
Copyright © 2011-2022 走看看