$python面向對象基礎

本文主要講述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類

這是全部類的祖先類。一個自定義類若是不指定繼承哪一個類,那它默認繼承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
相關文章
相關標籤/搜索