本文主要講述python面向對象的一些基礎語法。python
建立一個名爲Person類,繼承自object類(object類是全部類的祖先類),類體爲空:json
class Person(object): pass
建立一個Person類的實例:ssh
p1 = Person()
爲p1動態添加一個'name'屬性:函數
p1.name = 'Tom' print p1.name
Tom
爲p1動態添加方法(其實方法也能夠當作是對象實例的特殊屬性):code
import types p1.get_name = types.MethodType(lambda self:self.name,p1,Person) print p1.get_name()
Tom
再建立另一個Person對象:orm
p2 = Person() print p2.name
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-10-e3abcd8b0fdd> in <module>() 1 p2 = Person() ----> 2 print p2.name AttributeError: 'Person' object has no attribute 'name'
能夠看出爲p1對象動態添加的'name'屬性並不會影響到Person類的其餘對象。對象
class Person(object): # 這裏self爲實例方法的第一個必須的參數,必需要有,且要放在第一個;第二個name爲自定義必選參數,後面的kwargs是可選參數列表 def __init__(self,name,**kwargs): self.name = name for k,v in kwargs.iteritems(): # 設置實例屬性值 setattr(self,k,v)
p = Person('Tom',age = 19,gender = 'male') print p.name print p.age print p.gender
Tom 19 male
python中實例的屬性(包括屬性和方法)是根據命名來進行可見性約束的,規則以下:繼承
attr
內外部均可見ip
__attr__
預置屬性,內外部均可見,但不建議普通屬性這樣命名開發
_attr
內部可見、外部不可見(但只是倡議,並不是強制約束)
__attr
內部可見、外部不可見(強制約束)
舉例說明:
class Person(object): attr1 = 1 __attr2__ = 2 _attr3 = 3 __attr4 = 4
p = Person()
print p.attr1
1
print p.__attr2__
2
print p._attr3
3
print p.__attr4
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-20-47493f4f761b> in <module>() ----> 1 print p.__attr4 AttributeError: 'Person' object has no attribute '__attr4'
寫在類中,而非方法中的屬性,其可見性規則和實例屬性相似。
注:當實例修改了某個類屬性以後,實際上是建立了一個新的同名的實例屬性,並不會讓類屬性值自己真正發生改變。而實例屬性的訪問優先級是高於類屬性的。
類方法就是用@classmethod
裝飾器修飾的方法。`
這是全部類的祖先類。一個自定義類若是不指定繼承哪一個類,那它默認繼承object類,如:
class Person: pass p = Person() print isinstance(p,Person) print isinstance(p,object)
True True
def __init__(self,arg1,arg2,...): ...
在子類的構造方法中要調用父類的構造方法進行初始化,才能獲取到父類的實例屬性(獲取類屬性不須要),調用方式:
# SubClass:子類類名 super(SubClass,self).__init__(attr1,attr2,...) #這裏不用再寫'self'參數了
舉例:
class Person(object): attr = 1 def __init__(self,name,age): self.name = name self.age = age class Student(Person): def __init__(self,name,age,score): super(Student,self).__init__(name,age) self.score = score
s = Student('Tom',18,98)
print s
<__main__.Student object at 0x03A31D10>
print s.age print s.name print s.score print s.attr
18 Tom 98 1
小貼士:python做爲動態語言,調用實例的方法時,並不會去檢查類型的合法性,只要調的方法是實例有的而且參數正確,就能夠調用。
例如:只要一個對象實例有名爲'read'的方法,它就是一個file-like對象,就能夠做爲參數傳入json.load()函數中。
class A: pass class B(A): pass class C(A): pass class D(B,C): pass d = D() print isinstance(d,D) print isinstance(d,B) print isinstance(d,C) print isinstance(d,A)
True True True True
能夠看出B、C類都繼承了A類,而D類又同時繼承了B、C類,因此D類的對象同時也是A、B、C三個類的實例。
class Person(object): name = 'Tom' p = Person()
print isinstance(p,Person)
True
print isinstance([1,2,3],list)
True
print type(p)
<class '__main__.Person'>
print dir(p)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
print getattr(p,'name')
Tom
setattr(p,'age',19) print p.age
19
__str__(self)
和__repr__(self)
:用於print等顯示函數,前者用於給用戶看,後者給開發看。
__cmp__(self,s)
:用於cmp()
、sorted()
等和順序有關的函數,其中s爲另外一個同類型的對象。
__len__(self)
:用於len()
函數。
__add__(self,s)
、__sub__(self,s)
、__mul__(self,s)
、__div__(self,s)
:用於對象的加減乘除四則運算。
__int__(self)
:用於int()
函數。
__float__(self)
:用於float()
函數。
__slots__(self)
:返回一個字符串列表或元組,限制類能夠具備的屬性。
__call__(self)
:讓對象變成可調用的(用雙括號()
運算符調用)。
注:實現了__call__(self)
方法的對象就變成了能夠像函數那樣調用的了,因此python的對象和函數的區分其實不明顯。
舉例:
class Say(object): def __call__(self,a,b): print 'You say:{0} and {1}'.format(a,b) s = Say() s('hello','world')
You say:hello and world
@property
裝飾器:裝飾屬性的getter方法。
@attr.setter
裝飾器:裝飾屬性的setter方法。
舉例:
class Student(object): def __init__(self,name,score): self.name = name # 這裏score定義成一個私有的屬性 self.__score = score # 至關於getter方法 @property def score(self): return self.__score # 至關於setter方法 @score.setter def score(self,score): if score > 100 or score < 0: raise ValueError('Invalid score!') self.__score = score # 定義一個新的grade屬性 @property def grade(self): if self.__score >= 80: return 'A' elif self.__score < 60: return 'C' else: return 'B' s = Student('Tom',90) print s.grade s.score = 59 print s.grade print s.score
A C 59
s.score = -1
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-10-7a8b6a159a64> in <module>() ----> 1 s.score = -1 <ipython-input-9-9b3f1ca25afb> in score(self, score) 14 def score(self,score): 15 if score > 100 or score < 0: ---> 16 raise ValueError('Invalid score!') 17 self.__score = score 18 ValueError: Invalid score!
s.grade = 'C'
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-11-de53788b008a> in <module>() ----> 1 s.grade = 'C' AttributeError: can't set attribute