1. 程式人生 > >Python中類的特殊變量

Python中類的特殊變量

next() cls ont dir code hasattr methods ttr lose

特殊變量

  • 類似__xx,以雙下劃線開頭的實例變量名,就變成了一個私有變量(private),只有內部可以訪問,外部不能訪問;
  • 類似__xx__,以雙下劃線開頭,並且以雙下劃線結尾的,是特殊變量,特殊變量是可以直接訪問的,它不是private變量,下面會介紹Python中的常見特殊變量;
  • 類似_x,以單下劃線開頭的實例變量名,這樣的變量外部是可以訪問的,但是,按照約定俗成的規定,當你看到這樣的變量時,意思就是,“雖然我可以被訪問,但是請把我視為私有變量,不要隨意訪問”。

內置函數

  • type(),type()函數返回type類型

用法:

import types
type(
abc)==types.StringType type(uabc)==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(ua, 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

參考文檔:

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

Python中類的特殊變量