• Python中类的特殊变量


     特殊变量

    • 类似__xx,以双下划线开头的实例变量名,就变成了一个私有变量(private),只有内部可以访问,外部不能访问;
    • 类似__xx__,以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,它不是private变量,下面会介绍Python中的常见特殊变量;
    • 类似_x,以单下划线开头的实例变量名,这样的变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是请把我视为私有变量,不要随意访问”。

    内置函数

    • type(),type()函数返回type类型

    用法:

    import types
    type('abc')==types.StringType
    type(u'abc')==types.UnicodeType
    type([])==types.ListType
    type(str)==types.TypeType

    最后这种类型叫做TypeType,所有类型本身就是TypeType。

    也可以对函数或者类:

    • isinstance(),判断一个对象是否属于某个类型

    一个例子:

    class P(object):
        pass
    
    class C(P):
        pass
    
    p = P()
    c = C()
    print isinstance(p, P)
    print isinstance(c, P)
    print isinstance(p, C) # False
    print isinstance(c, C)

    如上,子类实例即是父类类型,也是子类类型,但父类实例不属于子类类型。

    isinstance()也可以代替type()的作用:

    isinstance('a', str)
    isinstance(u'a', unicode)
    isinstance('a', unicode) #False
    • dir(),获取对象的属性和方法列表
    • getattr(),获取对象的特定属性
    • hasattr(),对象是否存在某个属性
    • setattr(),设置对象的属性

    用法:

    class P(object):
        name = "cq"
        def __init__(self, age):
            self.age = age
    
    print hasattr(P, "name")    # True
    print hasattr(P, "age")     # False
    setattr(P, "age", 31)
    print getattr(P, "name")    # cq
    print getattr(P, "age")     # 31

    特殊变量

    __doc__

     定义文档字符串

     

     

     

     

    __dict__

    类的属性列表

     

     

     

    __class__

     

     

    __slots__

    对类的实例可以动态的绑定属性和方法,如下:

     

    from types import MethodType
    
    def set_age(self, age):
        self.age = age 
    
    
    class P(object):
        pass
    
    p = P() 
    p.name = 'chenqi'
    p.set_age = MethodType(set_age, p, P)  
    
    p.set_age(31)
    print p.name
    print p.age

    对一个实例添加的属性(或方法)仅在该实例有效,对其它实例不起作用。

     

    如果想让添加的方法对所有实例都生效,可以绑定到类上:

    P.set_age = MethodType(set_age, None, P)

    最后,__slots__的作用就是限制对类动态绑定的属性范围,例如:

    class P(object):
        __slots__ = ("name", "age")
        pass

    如上,除了"name"和"age"之外的属性就不能再增加了;

    注意:__slots__属性不会继承给子类,仅在当前类生效。

     

     

     

    __init__

    创建实例的时候,可以调用__init__方法做一些初始化的工作:

     

    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
        def print_score(self):
            print('%s: %s' % (self.name, self.score))

    与普通的实例方法类似,如果子类不重写__init__,实例化子类时,会自动调用父类的__init__;

    如果子类重写了__init__,实例化子类时,则只会调用子类的__init__,此时如果想使用父类的__init__,可以使用super函数,如下:

    class P(object):
        def __init__(self, name, score):
            self.name = name
            self.score = name
    
    
    class C(P):
        def __init__(self, name, score, age):
            super(C, self).__init__(name, score)
            self.age = age 
    
    c = C('cq', 100, 31) 

     

     

     

    __new__

    注意:__init__是实例创建之后调用的第一个方法,而__new__更像构造函数,它在__init__之前被调用。

    另外,__new__方法是一个静态方法,第一参数是cls,__new__方法必须返回创建出来的实例。

     

    例如,用__new__实现单例模式:

    class Singleton(object):
        def __new__(cls):
            # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
            if not hasattr(cls, 'instance'):
                cls.instance = super(Singleton, cls).__new__(cls)
            return cls.instance
     
    obj1 = Singleton()
    obj2 = Singleton()
     
    obj1.attr1 = 'value1'
    print obj1.attr1, obj2.attr1
    print obj1 is obj2

     

    __del__

    类似析构函数。

    class NewClass(object):
        num_count = 0 
    
        def __init__(self,name):
            self.name = name
            self.__class__.num_count += 1
            print name,NewClass.num_count
    
        def __del__(self):
            self.__class__.num_count -= 1
            print "Del",self.name,self.__class__.num_count
    
    a = NewClass("a")  
    b = NewClass("b")  
    c = NewClass("c")
    
    del a
    del b
    del c

    注意:用del删除一个对象的时候,不一定会调用__del__,只有在对象的引用计数为零时,__del__()才会被执行。

     

     

     

     

    __enter__

    __exit__

    这两个方法是用于支持with语句的上下文管理器。

    例如让文件句柄支持with语法的实现:

    class File(object):
        def __init__(self, file_name, method):
            self.file_obj = open(file_name, method)
        def __enter__(self):
            return self.file_obj
        def __exit__(self, type, value, traceback):
            self.file_obj.close()
    
    with File('demo.txt', 'w') as opened_file:
        opened_file.write('Hola!')

     

     

     

    __iter__

    next

    如果一个类想被用于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 > 100000: # 退出循环的条件
                raise StopIteration();
            return self.a # 返回下一个值

     

     

     

    __call__

    实例可以像函数一样调用。

     

    class Student(object):
    
        def __init__(self):
            self.name = "Michael"
    
        def __call__(self):
            print '__call__ called'
    
    
    s = Student()
    s()

    注意:callable()函数可用于判断一个对象是否可调用!

     

     

     

    __str__,返回用户看到的字符串

    __repr__,返回开发者看到的字符串(用于调试)

    # test.py
    class P(object):
        def __str__(self):
            return "__str__ called"
    
        def __repr__(self):
            return "__repr__ called"
    
    p = P() 

    可以看下__str__和__repr__的区别:

    >>> from test import p
    >>> p
    __repr__ called
    >>> print p
    __str__ called

     

     

     

     

    __getitem__

    __setitem__

    __delitem__

    支持下标(或切片)操作的函数, 

     

     例如:

    class Fib(object):
        def __getitem__(self, n): 
            if isinstance(n, int):
                a, b = 1, 1
                for x in range(n):
                    a, b = b, a + b 
                return a
    if isinstance(n, slice): start = n.start stop = n.stop a, b = 1, 1 L = [] for x in range(stop): if x >= start: L.append(a) a, b = b, a + b return L fib = Fib() print fib[10] print fib[0:10]

     

     

    __getattr__

    __getattribute__

    __setattr__

    __delattr__

    支持点操作(即 "对象.属性" 访问方式),

     

    当访问不存在的属性时,才会使用__getattr__  方法.

     

    class Student(object):
    
        def __init__(self):
            self.name = "Michael"
    
        def __getattr__(self, attr):
            print '__getattr__ called'
            if attr=='score':
                return 99
            elif attr=='name':
                return "Tom"
    
    
    s = Student()
    print s.score       # 99
    print s.name        # Michael

    Python的字典支持下标操作,但不支持 "." 操作,如果想让其支持,如下实现:

     

    class Storage(dict):
        __slots__ = ()
        """
        A Storage object is like a dictionary except `obj.foo` can be used
        in addition to `obj['foo']`.
    
            >>> o = Storage(a=1)
            >>> o.a
            1
            >>> o['a']
            1
            >>> o.a = 2
            >>> o['a']
            2
            >>> del o.a
            >>> o.a
            Traceback (most recent call last):
                ...
            AttributeError: 'a'
            >>> 'b' in o
            False
    
        """
    
        def __getattr__(self, key):
            try:
                return self[key]
            except KeyError, k:
                raise AttributeError(k)
    
        def __setattr__(self, key, value):
            self[key] = value
    
        def __delattr__(self, key):
            try:
                del self[key]
            except KeyError, k:
                raise AttributeError(k)
       
        def __repr__(self):
            return '<Storage ' + dict.__repr__(self) + '>'

     

     

     

     

     

    参考文档:

    https://infohost.nmt.edu/tcc/help/pubs/python/web/special-methods.html

     

     

     

     

  • 相关阅读:
    Php扩展--protocolbuffers消息打包
    Php扩展--seasLog日志扩展安装
    PHP系统编程--03.PHP进程信号处理
    PHP系统编程--01.多进程与多线程
    PHP系统编程--02.PHP守护进程化
    linux shell 之if-------用if做判断
    Connection:Keep-alive
    Http报头Accept与Content-Type的区别
    json解析
    JSON-lib框架,转换JSON、XML不再困难
  • 原文地址:https://www.cnblogs.com/chenny7/p/7338502.html
Copyright © 2020-2023  润新知