標籤:

python特殊變數

特殊變數

  • 類似__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

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) + >


推薦閱讀:

TAG:Python |