pythonic和面向?qū)ο?/h1>

1 類(lèi)的定義

假設(shè)需要定義一個(gè)人

# person.py
class Person:
    def __init__(self, age=18, code=3):
        self.age, self.code = age, code

    def total(self):
        return self.age + self.code

上述是一個(gè)構(gòu)造函數(shù)国觉,如果在java里面我們這樣玩,會(huì)這樣寫(xiě):

public class Person{
     private int age;
     private int code;

     public Person(age,code){
        this.age = age;
        this.code = code
  }
     getter,setter省略...
}

我們需要注意的是python這種連等方式探熔。

from person import *
p = Person(10, 10)  # __init__ 被調(diào)用
type(p)
<class 'person.Person'>
p.age, p.code
(10, 10)

我們?cè)趐erson初始化的方法上寫(xiě)了昌阿,2個(gè)默認(rèn)值。
對(duì)一切皆對(duì)象的 Python 來(lái)說(shuō)言疗,類(lèi)自己當(dāng)然也是對(duì)象:

type(Person)
<class 'type'>
dir(Person)
['__class__', '__delattr__', '__dict__', ..., '__init__','total' ...]
Person.__class__
<class 'type'>

使用dir()函數(shù)可以查看對(duì)像內(nèi)所有屬于及方法晴圾,在python中任何東西都是對(duì)像,一種數(shù)據(jù)類(lèi)型噪奄,一個(gè)模塊等疑务,都有自己的屬性和方法,除了常用方法外梗醇,其它的你不需要全部記住它知允,交給dir()函數(shù)就好了。

查看列表都有哪些方法

dir([ ])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__',
 '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__',
 '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__',
 '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count',
 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

很好叙谨,我們的到了列表所有的方法温鸽,熟悉的有append,insert等,具體不說(shuō)明了手负。好我們繼續(xù)看

class Person:
    ...
    def set(self, x, y):
        self.x, self.y = x, y

p = Person(10, 10)
p.set(0, 0)
p.x, p.y
(0, 0)

p.set(...) 其實(shí)只是一個(gè)語(yǔ)法糖涤垫,你也可以寫(xiě)成 Point.set(p, ...),這樣就能明顯看出 p 就是 self 參數(shù)了:

Point.set(p, 0, 0)
p.x, p.y
(0, 0)

上面這種寫(xiě)法竟终,是一樣的蝠猬。

訪(fǎng)問(wèn)控制

Python 沒(méi)有 public / protected / private 這樣的訪(fǎng)問(wèn)控制,如果你非要表示“私有”统捶,習(xí)慣是加雙下劃線(xiàn)前綴榆芦。

class Point:
    def __init__(self, x=0, y=0):
        self.__x, self.__y = x, y
 
    def set(self, x, y):
        self.__x, self.__y = x, y
 
    def __f(self):
        pass

__x、__y 和 __f 就相當(dāng)于私有了:

>>> p.__x
...
AttributeError: 'Point' object has no attribute '__x'
>>> p.__f()
...
AttributeError: 'Point' object has no attribute '__f'

嘗試打印 Point 實(shí)例:

>>> p = Point(10, 10)
>>> p
<point.Point object at 0x000000000272AA20>

可以看到我們打印出了這個(gè)p對(duì)象喘鸟,如果我們想換一種方式呢匆绣?

class Point:
    def __repr__(self):
        return 'Point({}, {})'.format(self.__x, self.__y)

>>> repr(p)
'Point(10, 10)'

我們?cè)谝粋€(gè)類(lèi)中自定義了一個(gè)repr方法,調(diào)用他什黑。下面我們來(lái)看一些野路子崎淳。。愕把。
裝飾器@staticmethod和@classmethod有什么區(qū)別?

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)"%(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)"%(cls,x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)"%x

a=A()

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1) //注意傳遞的是cls

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

一個(gè)簡(jiǎn)單的例子很直接說(shuō)明了classmethod的用法

class Kls(object):
    no_inst = 0

    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1

    @classmethod
    def get_no_of_instance(cls_obj):
        return cls_obj.no_inst

ik1 = Kls()
ik2 = Kls()
ik3 = Kls()

print ik1.get_no_of_instance()
print Kls.get_no_of_instance()
// output 3

2 類(lèi)的繼承

舉一個(gè)教科書(shū)中最常見(jiàn)的例子拣凹。Circle 和 Rectangle 繼承自 Shape,不同的圖形恨豁,面積(area)計(jì)算方式不同嚣镜。

# shape.py
 
class Shape:
    def area(self):
        return 0.0
        
class Circle(Shape):
    def __init__(self, r=0.0):
        self.r = r
 
    def area(self):
        return math.pi * self.r * self.r
 
class Rectangle(Shape):
    def __init__(self, a, b):
        self.a, self.b = a, b
 
    def area(self):
        return self.a * self.b

>>> from shape import *
>>> circle = Circle(3.0)
>>> circle.area()
28.274333882308138
>>> rectangle = Rectangle(2.0, 3.0)
>>> rectangle.area()
6.0

繼承的方式很簡(jiǎn)單,在類(lèi)名上加個(gè)括號(hào)就行圣絮。
如果 Circle 沒(méi)有定義自己的 area:

class Circle(Shape):
    pass
>>> Shape.area is Circle.area
True

一旦 Circle 定義了自己的 area祈惶,從 Shape 繼承而來(lái)的那個(gè) area 就被重寫(xiě)(overwrite)了:

>>> from shape import *
>>> Shape.area is Circle.area
False

通過(guò)類(lèi)的字典更能明顯地看清這一點(diǎn):

>>> Shape.__dict__['area']
<function Shape.area at 0x0000000001FDB9D8>
>>> Circle.__dict__['area']
<function Circle.area at 0x0000000001FDBB70>

所以,子類(lèi)重寫(xiě)父類(lèi)的方法,其實(shí)只是把相同的屬性名綁定到了不同的函數(shù)對(duì)象捧请》采可見(jiàn) Python 是沒(méi)有覆寫(xiě)(override)的概念的。

甚至可以動(dòng)態(tài)的添加方法:

class Circle(Shape):
    ...
    #  def area(self):
        #  return math.pi * self.r * self.r
 
# 為 Circle 添加 area 方法疹蛉。
Circle.area = lambda self: math.pi * self.r * self.r

lambda表達(dá)式返回一個(gè)函數(shù)對(duì)象活箕。
這樣吧我們寫(xiě)一個(gè)完整的繼承代碼把


輸出

3 多態(tài)

如前所述,Python 沒(méi)有覆寫(xiě)(override)的概念可款。嚴(yán)格來(lái)講育韩,Python 并不支持「多態(tài)」。

#!/usr/bin/env Python
class Animal:
    def __init__(self, name=""):
        self.name = name

    def talk(self):
        pass

class Cat(Animal):
    def talk(self):
        print "Meow!"

class Dog(Animal):
    def talk(self):
        print "Woof!"

a = Animal()
a.talk()

c = Cat("Missy")
c.talk()

d = Dog("Rocky")
d.talk()

其實(shí)我沒(méi)有虎你闺鲸,python里的多態(tài)看起來(lái)確實(shí)很low筋讨。。摸恍。下面講一個(gè)知識(shí)點(diǎn)

#!/usr/bin/env Python
class ProtectMe:
    def __init__(self):
        self.me = "qiwsir"
        self.__name = "kivi"

    @property
    def name(self):
        return self.__name

if __name__ == "__main__":
    p = ProtectMe()
    print p.name

怎么樣知道如何訪(fǎng)問(wèn)私有屬性了把悉罕。。
最后給大家?guī)?lái)一波福利立镶,我這里只貼代碼了壁袄,大家細(xì)看

itertools庫(kù)

迭代器(生成器)在Python中是一種很常用也很好用的數(shù)據(jù)結(jié)構(gòu),比起列表(list)來(lái)說(shuō)媚媒,迭代器最大的優(yōu)勢(shì)就是延遲計(jì)算嗜逻,按需使用,從而提高開(kāi)發(fā)體驗(yàn)和運(yùn)行效率缭召,以至于在Python 3中map,filter等操作返回的不再是列表而是迭代器栈顷。
itertools.accumulate

>>> import itertools
>>> x = itertools.accumulate(range(10))
>>> print(list(x))
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]

原函數(shù)是這樣寫(xiě)的

def accumulate(iterable, func=operator.add):
    'Return running totals'
    # accumulate([1,2,3,4,5]) --> 1 3 6 10 15
    # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
    it = iter(iterable)
    try:
        total = next(it)
    except StopIteration:
        return
    yield total
    for element in it:
        total = func(total, element)
        yield total

data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]
>>> list(accumulate(data, operator.mul))     # running product
[3, 12, 72, 144, 144, 1296, 0, 0, 0, 0]

itertools.chain

>>> x = itertools.chain(range(3), range(4), [3,2,1])
>>> print(list(x))
[0, 1, 2, 0, 1, 2, 3, 3, 2, 1]

itertools.combinations
求列表或生成器中指定數(shù)目的元素不重復(fù)的所有組合

>>> x = itertools.combinations(range(4), 3)
>>> print(list(x))
[(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]

itertools.compress
按照真值表篩選元素

>>> x = itertools.compress(range(5), (True, False, True, True, False))
>>> print(list(x))
[0, 2, 3]

itertools.islice

def islice(iterable, *args):
    # islice('ABCDEFG', 2) --> A B
    # islice('ABCDEFG', 2, 4) --> C D
    # islice('ABCDEFG', 2, None) --> C D E F G
    # islice('ABCDEFG', 0, None, 2) --> A C E G
    s = slice(*args)
    it = iter(range(s.start or 0, s.stop or sys.maxsize, s.step or 1))
    try:
        nexti = next(it)
    except StopIteration:
        return
    for i, element in enumerate(iterable):
        if i == nexti:
            yield element
            nexti = next(it)

itertools.count(start=0, step=1)

 # count(10) --> 10 11 12 13 14 ...
    # count(2.5, 0.5) -> 2.5 3.0 3.5 ...
    n = start
    while True:
        yield n
        n += step
>>> x = itertools.count(start=20, step=-1)
>>> print(list(itertools.islice(x, 0, 5, 2)))
[20, 18, 16, 14,12]

itertools.cycle

>>> x = itertools.cycle('ABC')
>>> print(list(itertools.islice(x, 0, 10, 1)))
['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A']

itertools.filterfalse

>>> x = itertools.filterfalse(lambda e: e < 5, (1, 5, 3, 6, 9, 4))
>>> print(list(x))
[5, 6, 9]

itertools.groupby

>>> x = itertools.groupby(range(10), lambda x: x < 5 or x > 8)                                                                                                 
>>> for condition, numbers in x:                                                  
...     print(condition, list(numbers))                                                                                                        
True [0, 1, 2, 3, 4]                                                              
False [5, 6, 7, 8]                                                                
True [9]

好了,今天的講解也到這里了恼琼,我得去寫(xiě)代碼了妨蛹。。晴竞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市狠半,隨后出現(xiàn)的幾起案子噩死,更是在濱河造成了極大的恐慌,老刑警劉巖神年,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件已维,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡已日,警方通過(guò)查閱死者的電腦和手機(jī)垛耳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人堂鲜,你說(shuō)我怎么就攤上這事栈雳。” “怎么了缔莲?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵哥纫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我痴奏,道長(zhǎng)蛀骇,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任读拆,我火速辦了婚禮擅憔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘檐晕。我一直安慰自己暑诸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布棉姐。 她就那樣靜靜地躺著屠列,像睡著了一般。 火紅的嫁衣襯著肌膚如雪伞矩。 梳的紋絲不亂的頭發(fā)上笛洛,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音乃坤,去河邊找鬼苛让。 笑死,一個(gè)胖子當(dāng)著我的面吹牛湿诊,可吹牛的內(nèi)容都是我干的狱杰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼厅须,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼仿畸!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起朗和,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤错沽,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后眶拉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體千埃,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年忆植,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了放可。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谒臼。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖耀里,靈堂內(nèi)的尸體忽然破棺而出蜈缤,到底是詐尸還是另有隱情,我是刑警寧澤备韧,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布劫樟,位于F島的核電站,受9級(jí)特大地震影響织堂,放射性物質(zhì)發(fā)生泄漏叠艳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一易阳、第九天 我趴在偏房一處隱蔽的房頂上張望附较。 院中可真熱鬧,春花似錦潦俺、人聲如沸拒课。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)早像。三九已至,卻和暖如春肖爵,著一層夾襖步出監(jiān)牢的瞬間卢鹦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工劝堪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冀自,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓秒啦,卻偏偏與公主長(zhǎng)得像熬粗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子余境,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容