成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

python學(xué)習(xí)筆記-魔術(shù)方法,讓自定義類更像內(nèi)置類型

changfeng1050 / 2520人閱讀

摘要:的魔術(shù)方法是中那些預(yù)定義的像類型的函數(shù)。使用的魔術(shù)方法的最大優(yōu)勢(shì)在于提供了簡(jiǎn)單的方法讓對(duì)象可以表現(xiàn)得像內(nèi)置類型一樣。廖雪峰老師教程里寫的是方法,不知道為啥。

Python的魔術(shù)方法是Python中那些預(yù)定義的像__XXX__類型的函數(shù)。
使用Python的魔術(shù)方法的最大優(yōu)勢(shì)在于python提供了簡(jiǎn)單的方法讓對(duì)象可以表現(xiàn)得像內(nèi)置類型一樣。

__str__函數(shù)

__str__函數(shù)用于處理打印實(shí)例本身的時(shí)候的輸出內(nèi)容。如果沒有覆寫該函數(shù),則默認(rèn)輸出一個(gè)對(duì)象名稱和內(nèi)存地址。
例如:

>>> class Student(object):
...     def __init__(self,name):
...             self._name = name
...
>>> print Student()

輸出:<__main__.Student object at 0x0000000002A929E8>.
那么我們?nèi)绾巫屳敵龅慕Y(jié)果可讀性更高一點(diǎn)呢?我們可以覆寫__str__函數(shù)。例如

>>> class Student(object):
...     def __init__(self, name):
...             self._name = name
...     def __str__(self):
...             return  "I"m a student, named %s" % self._name
...
>>> print Student("Charlie")

輸出結(jié)果就是:I"m a student, named Charlie.
我們將str()函數(shù)作用于該對(duì)象的時(shí)候,其實(shí)是調(diào)用了該對(duì)象的__str__函數(shù)。

_repr_ 函數(shù)

__repr__也是將對(duì)象序列化,但是__repr__更多的是給python編譯器看的。__str__更多的是可讀性(readable)。
我們將repr()函數(shù)作用于摸某一個(gè)對(duì)象的時(shí)候,調(diào)用的其實(shí)就是該函數(shù)的__repr__函數(shù)。

repr()成對(duì)的是eval()函數(shù)。eval()函數(shù)是將序列化后的對(duì)象重新轉(zhuǎn)為對(duì)象。前提是該對(duì)象實(shí)現(xiàn)了__repr__函數(shù)。

上面這一段話基于自己的理解,不知道對(duì)錯(cuò)。

>>> item = [1,2,3]
>>> repr(item)
"[1, 2, 3]"
>>> other_item = eval(repr(item))
>>> other_item[1]
2
__iter__函數(shù)

我們經(jīng)常對(duì)list或者tuple使用for...in...來迭代。那是list繼承自Iterable。Iterable實(shí)現(xiàn)了__iter__函數(shù)。

要想將一個(gè)自定義的對(duì)象變成一個(gè)可迭代的對(duì)象,那么必須要實(shí)現(xiàn)兩個(gè)方法:__iter__next.

__iter__函數(shù)返回一個(gè)對(duì)象。迭代的時(shí)候則會(huì)不斷地調(diào)用next函數(shù)拿到下一個(gè)值,直到捕獲到StopIteration停止。
廖雪峰老師教程里寫的是__next__方法,不知道為啥。

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1

    def __iter__(self):
        return self

    def next(self):
        self.a, self.b = self.b, self.a + self.b
        if self.a > 10000:
            raise StopIteration
        return self.a


for i in Fib():
    print i
__getitem__函數(shù)

上面通過實(shí)現(xiàn)__iter__函數(shù)實(shí)現(xiàn)對(duì)象的迭代。
那么如何實(shí)現(xiàn)對(duì)象按下標(biāo)取出元素呢。
這是通過實(shí)現(xiàn)對(duì)象的__getitem__方法。
我們來舉一個(gè)?子。我們新建了一個(gè)類MyList,我們要辦它實(shí)現(xiàn)普通list的一些功能,比如(1)根據(jù)下標(biāo)獲取值;(2)正數(shù)順序單步長(zhǎng)切片 (3)任意步長(zhǎng)切片

class MyList(object):
    def __init__(self, *args):
        self.numbers = args

    def __getitem__(self, item):
        return self.numbers[item]


my_list = MyList(1, 2, 3, 4, 6, 5, 3)
print my_list[2]

當(dāng)然,上面實(shí)現(xiàn)了根據(jù)下標(biāo)獲取值。但是這還不夠。我們還需要實(shí)現(xiàn)切片功能。例如my_list[1:3].
我們對(duì)對(duì)象進(jìn)行切片操作的時(shí)候,調(diào)用的氣勢(shì)也是__getitem__函數(shù)。此時(shí),該函數(shù)獲取到的并不是int對(duì)象,而是slice對(duì)象。
例如下面的代碼

class MyList(object):
    def __init__(self, *args):
        self.numbers = args

    def __getitem__(self, item):
        if isinstance(item, int):
            return self.numbers[item]
        elif isinstance(item, slice):
            # 寫習(xí)慣了其他語(yǔ)言,差點(diǎn)忘記了三元運(yùn)算符的格式了,吼吼吼。
            # 下面句三元運(yùn)算符的意思是,若為空,則為切片從0開始。
            start = item.start if item.start is not None else 0
            # 下面句三元運(yùn)算符的意思是,若為空,則為切片到最末端結(jié)束。
            stop = item.stop if item.stop is not None else len(self.numbers)
            return self.numbers[start:stop]


my_list = MyList(1, 2, 3, 4, 6, 5, 3)
print my_list[2:5]

上面的代碼終于實(shí)現(xiàn)了切片功能,但是還沒考慮負(fù)數(shù)呢。那么我們加一把勁再來改一下。代碼如下:

class MyList(object):
    def __init__(self, *args):
        self.numbers = args

    def __getitem__(self, item):
        if isinstance(item, int):
            return self.numbers[item]
        elif isinstance(item, slice):
            start = item.start if item.start is not None else 0
            stop = item.stop if item.stop is not None else len(self.numbers)

            length = len(self.numbers)
            start = length + start + 1 if start < 0 else start
            stop = length + stop + 1 if stop < 0 else stop
            return self.numbers[start:stop]

my_list = MyList(1, 2, 3, 4, 6, 5, 3)
print my_list[1:-1]

哇塞,寫完了,棒棒棒

_getattar_

在調(diào)用某一個(gè)對(duì)象不存在的屬性或者方法的時(shí)候,會(huì)拋出一個(gè)一個(gè)AttributeError錯(cuò)誤。
但是如果我們實(shí)現(xiàn)了類中的魔術(shù)方法__getattar__,那么在調(diào)用不存在的屬性或者方法的時(shí)候,就會(huì)調(diào)用該魔術(shù)方法。

class Apple(object):
    def __getattr__(self, item):
        if item == "attar1":
            return "print"
        if item == "method1":
            return lambda x: "hello %s" % x


apple = Apple()
print apple.attar1
print apple.method1

__getattar__函數(shù)一個(gè)重要的適用場(chǎng)景就是實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用。例如我們?cè)谡{(diào)用某一個(gè)api的時(shí)候:

GET users/articles/index

那么我們就希望我們的代碼可以實(shí)現(xiàn)`Api.users.articles.index這么調(diào)用。
思考一下,要實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,最重要的就是每一個(gè)調(diào)用都是返回一個(gè)實(shí)例~~。

# coding=utf-8
class Api(object):
    def __init__(self, path=""):
        self._path = path

    def __getattr__(self, name):
        return Api("%s/%s" % (self._path, name))

    # 定義一個(gè)Post方法來發(fā)送請(qǐng)求
    def post(self):
        print self._path


api = Api()
api.user.articles.index.post()

廖雪峰在他的教程中給我們出了一個(gè)題目:
例如調(diào)用github的api:users/:user/repos一樣,中間的user名需要?jiǎng)討B(tài)替換。
我們希望能api.users("charlie").repos這么調(diào)用。那么代碼該如何實(shí)現(xiàn)呢?這可能需要用到另一個(gè)方法__call__

_call_ 函數(shù)

一個(gè)對(duì)象既有屬性,又有方法。我們?cè)谡{(diào)用一個(gè)實(shí)例的方法的時(shí)候,我們可以使用instance.method()的形式調(diào)用。
其實(shí)也可以將實(shí)例本身看成一個(gè)函數(shù)用來調(diào)用,我們需要做的就是實(shí)現(xiàn)__call__函數(shù)本身。

class Apple(object):
    def __call__(self, *args, **kwargs):
        return args


apple = Apple()
print apple("yes", "no")

此時(shí)我們?cè)賮砜匆幌律厦嫣岬降膶?shí)現(xiàn)api.users("charlie").repos鏈?zhǔn)秸{(diào)用的方法。

# coding=utf-8
class Api(object):
    def __init__(self, path=""):
        self._path = path

    def __getattr__(self, name):
        return Api("%s/%s" % (self._path, name))

    def __call__(self, args):
        self._path = "%s/%s" % (self._path, args)
        return Api(self._path)

    # 定義一個(gè)Post方法來發(fā)送請(qǐng)求
    def post(self):
        print self._path


api = Api()
api.users("Charlie").index.post()

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/38334.html

相關(guān)文章

  • 聊聊技術(shù)寫作的個(gè)人體會(huì)

    摘要:由此看來,的官方文檔就把當(dāng)成內(nèi)置函數(shù),這個(gè)認(rèn)識(shí)錯(cuò)誤是有根源的等到的時(shí)候,官方把錯(cuò)誤改正過來了,然而改得并不徹底。使用進(jìn)行判斷,結(jié)果為的才是內(nèi)置函數(shù)。 showImg(https://segmentfault.com/img/bVbm3Bu?w=5184&h=3456);有群友問過,是什么原因使我開始寫技術(shù)公眾號(hào),又是什么動(dòng)力讓我堅(jiān)持寫的。 在我看來,寫作是一件不能敷衍的事,通過寫作來學(xué)...

    madthumb 評(píng)論0 收藏0
  • Python學(xué)習(xí)之路28-符合Python風(fēng)格的對(duì)象

    摘要:本篇繼續(xù)學(xué)習(xí)之路,實(shí)現(xiàn)更多的特殊方法以讓自定義類的行為跟真正的對(duì)象一樣。之所以要讓向量不可變,是因?yàn)槲覀冊(cè)谟?jì)算向量的哈希值時(shí)需要用到和的哈希值,如果這兩個(gè)值可變,那向量的哈希值就能隨時(shí)變化,這將不是一個(gè)可散列的對(duì)象。 《流暢的Python》筆記。本篇是面向?qū)ο髴T用方法的第二篇。前一篇講的是內(nèi)置對(duì)象的結(jié)構(gòu)和行為,本篇?jiǎng)t是自定義對(duì)象。本篇繼續(xù)Python學(xué)習(xí)之路20,實(shí)現(xiàn)更多的特殊方法以讓...

    Eric 評(píng)論0 收藏0
  • es6學(xué)習(xí)筆記-Symbol_v1.0_byKL

    摘要:它是語(yǔ)言的第七種數(shù)據(jù)類型前六種是布爾值字符串?dāng)?shù)值對(duì)象。為了防止沖突這就是引入的原因。指向了這個(gè)內(nèi)部方法調(diào)用了返回對(duì)象的屬性等于一個(gè)布爾值,表示該對(duì)象使用時(shí),是否可以展開。數(shù)組的默認(rèn)行為是可以展開返回對(duì)象的屬性,指向當(dāng)前對(duì)象的構(gòu)造函數(shù)。 es6學(xué)習(xí)筆記-Symbol_v1.0 基本抄了一次內(nèi)容,有很多只是知道其然并不知其所以然,不過也算是加深了一次印象,另外每段代碼我都有手動(dòng)執(zhí)行過. E...

    Lowky 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<