国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python學(xué)習(xí)之路28-符合Python風(fēng)格的對(duì)象

Eric / 2923人閱讀

摘要:本篇繼續(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)更多的特殊方法以讓自定義類的行為跟真正的Python對(duì)象一樣。
1. 前言

本篇要討論的內(nèi)容如下,重點(diǎn)放在了對(duì)象的各種輸出形式上:

實(shí)現(xiàn)用于生成對(duì)象其他表示形式的內(nèi)置函數(shù)(如repr()bytes()等);

使用一個(gè)類方法實(shí)現(xiàn)備選構(gòu)造方法;

擴(kuò)展內(nèi)置的format()函數(shù)和str.format()方法使用的格式微語言;

實(shí)現(xiàn)只讀屬性;

實(shí)現(xiàn)對(duì)象的可散列;

利用__slots__節(jié)省內(nèi)存;

如何以及何時(shí)使用@classmethod@staticmethd裝飾器;

Python的私有屬性和受保護(hù)屬性的用法、約定和局限。

本篇將通過實(shí)現(xiàn)一個(gè)簡(jiǎn)單的二維歐幾里得向量類型,來涵蓋上述內(nèi)容。

不過在開始之前,我們需要補(bǔ)充幾個(gè)概念:

repr():以便于開發(fā)者理解的方式返回對(duì)象的字符串表示形式,它調(diào)用對(duì)象的__repr__特殊方法;

str():以便于用戶理解的方式返回對(duì)象的字符串表示形式,它調(diào)用對(duì)象的__str__特殊方法;

bytes():獲取對(duì)象的字節(jié)序列表示形式,它調(diào)用對(duì)象的__bytes__特殊方法;

format()str.format()格式化輸出對(duì)象的字符串表示形式,調(diào)用對(duì)象的__format__特殊方法。

2. 自定義向量類Vector2d

我們希望這個(gè)類具備如下行為:

# 代碼1
>>> v1 = Vector2d(3, 4)
>>> print(v1.x, v1.y)  # Vector2d實(shí)例的分量可直接通過實(shí)例屬性訪問,無需調(diào)用讀值方法
3.0 4.0
>>> x, y = v1  # 實(shí)例可拆包成變量元組
>>> x, y
(3.0, 4.0)
>>> v1  # 我們希望__repr__返回的結(jié)果類似于構(gòu)造實(shí)例的源碼
Vector2d(3.0, 4.0)
>>> v1_clone = eval(repr(v1))  # 只是為了說明repr()返回的結(jié)果能用來生成實(shí)例
>>> v1 == v1_clone  # Vector2d需支持 == 運(yùn)算符
True
>>> print(v1)  # 我們希望__str__方法以如下形式返回實(shí)例的字符串表示
(3.0, 4.0)
>>> octets = bytes(v1)  # 能夠生成字節(jié)序列
>>> octets
b"dx00x00x00x00x00x00x08@x00x00x00x00x00x00x10@"
>>> abs(v1)  # 能夠求模
5.0
>>> bool(v1), bool(Vector2d(0, 0))  # 能進(jìn)行布爾運(yùn)算
(True, False)

Vector2d的初始版本如下:

# 代碼2
from array import array
import math

class Vector2d:
    # 類屬性,在Vector2d實(shí)例和字節(jié)序列之間轉(zhuǎn)換時(shí)使用
    typecode = "d"    # 轉(zhuǎn)換成C語言中的double類型

    def __init__(self, x, y):
        self.x = float(x)  # 構(gòu)造是就轉(zhuǎn)換成浮點(diǎn)數(shù),盡早在構(gòu)造階段就捕獲錯(cuò)誤
        self.y = float(y)

    def __iter__(self): # 將Vector2d實(shí)例變?yōu)榭傻鷮?duì)象
        return (i for i in (self.x, self.y))  # 這是生成器表達(dá)式!

    def __repr__(self):
        class_name = type(self).__name__ # 獲取類名,沒有采用硬編碼
        # 由于Vector2d實(shí)例是可迭代對(duì)象,所以*self會(huì)把x和y提供給format函數(shù)
        return "{}({!r}, {!r})".format(class_name, *self)

    def __str__(self):
        return str(tuple(self)) # 由可迭代對(duì)象構(gòu)造元組

    def __bytes__(self):
        # ord()返回字符的Unicode碼位;array中的數(shù)組的元素是double類型
        return (bytes([ord(self.typecode)]) + bytes(array(self.typecode, self)))

    def __eq__(self, other): # 這樣實(shí)現(xiàn)有缺陷,Vector(3, 4) == [3, 4]也會(huì)返回True
        return tuple(self) == tuple(other)  # 但這個(gè)缺陷會(huì)在后面章節(jié)修復(fù)

    def __abs__(self): # 計(jì)算平方和的非負(fù)數(shù)根
        return math.hypot(self.x, self.y)

    def __bool__(self): # 用到了上面的__abs__來計(jì)算模,如果模為0,則是False,否則為True
        return bool(abs(self))
3. 備選構(gòu)造方法

初版Vector2d可將它的實(shí)例轉(zhuǎn)換成字節(jié)序列,但卻不能從字節(jié)序列構(gòu)造Vector2d實(shí)例,下面添加一個(gè)方法實(shí)現(xiàn)此功能:

# 代碼3
class Vector2d:
    -- snip --
    @classmethod
    def frombytes(cls, octets): # 不用傳入self參數(shù),但要通過cls傳入類本身
        typecode = chr(octets[0]) # 從第一個(gè)字節(jié)中讀取typecode,chr()將Unicode碼位轉(zhuǎn)換成字符
        # 使用傳入的octets字節(jié)序列構(gòu)建一個(gè)memoryview,然后根據(jù)typecode轉(zhuǎn)換成所需要的數(shù)據(jù)類型
        memv = memoryview(octets[1:]).cast(typecode)
        return cls(*memv)  # 拆包轉(zhuǎn)換后的memoryview,然后構(gòu)造一個(gè)Vector2d實(shí)例,并返回
4. classmethod與staticmethod

代碼3中用到了@classmethod裝飾器,與它相伴的還有@staticmethod裝飾器。

從上述代碼可以看出,classmethod定義的是傳入而不是傳入實(shí)例的方法,即傳入的第一個(gè)參數(shù)必須是,而不是實(shí)例classmethod改變了調(diào)用方法的方式,但是,在實(shí)際調(diào)用這個(gè)方法時(shí),我們不需要手動(dòng)傳入cls這個(gè)參數(shù),Python會(huì)自動(dòng)傳入。(按照傳統(tǒng),第一個(gè)參數(shù)一般命名為cls,當(dāng)然你也可以另起名)

staticmethod也會(huì)改變方法的調(diào)用方式,但第一個(gè)參數(shù)不是特殊值,既不是cls,也不是self,就是用戶傳入的普通參數(shù)。以下是它們的用法對(duì)比:

# 代碼4
>>> class Demo:
...     @classmethod
...     def klassmeth(*args):
...         return args  # 返回傳入的全部參數(shù)
...     @staticmethod
...     def statmeth(*args):
...         return args  # 返回傳入的全部參數(shù)
...
>>> Demo.klassmeth()
(,) # 不管如何調(diào)用Demo.klassmeth,它的第一個(gè)參數(shù)始終是Demo類自己
>>> Demo.klassmeth("spam")
(, "spam")
>>> Demo.statmeth()
()   # Demo.statmeth的行為與普通函數(shù)類似
>>> Demo.statmeth("spam")
("spam",)

classmethod很有用,但staticmethod一般都能找到很方便的替代方案,所以staticmethod并不是必須的。

5. 格式化顯示

內(nèi)置的format()函數(shù)和str.format()方法把各個(gè)類型的格式化方式委托給相應(yīng)的.__format__(format_spec)方法。format_spec是格式說明符,它是:

format(my_obj, format_spec)的第二個(gè)參數(shù);

也是str.format()方法的格式字符串,{}里替換字段中冒號(hào)后面的部分,例如:

# 代碼5
>>> brl = 1 / 2.43
>>> "1 BRL = {rate:0.2f} USD".format(rate=brl)  # 此時(shí) format_spec為"0.2f"

其中,冒號(hào)后面的0.2f是格式說明符,冒號(hào)前面的rate是字段名稱,與格式說明符無關(guān)。格式說明符使用的表示法叫格式規(guī)范微語言(Format Specification Mini-Language)。格式規(guī)范微語言為一些內(nèi)置類型提供了專門的表示代碼,比如b表示二進(jìn)制的int類型;同時(shí)它還是可擴(kuò)展的,各個(gè)類可以自行決定如何解釋format_spec參數(shù),比如時(shí)間的轉(zhuǎn)換格式%H:%M:%S,就可用于datetime類型,但用于int類型則可能報(bào)錯(cuò)。

如果類沒有定義__format__方法,則會(huì)返回__str__的結(jié)果,比如我們定義的Vector2d類型就沒有定義__format__方法,但依然可以調(diào)用format()函數(shù):

# 代碼6
>>> v1 = Vector2d(3, 4)
>>> format(v1)
"(3.0, 4.0)"

但現(xiàn)在的Vector2d在格式化顯示上還有缺陷,不能向format()傳入格式說明符:

>>> format(v1, ".3f")
Traceback (most recent call last):
   -- snip --
TypeError: non-empty format string passed to object.__format__

現(xiàn)在我們來為它定義__format__方法。添加自定義的格式代碼,如果格式說明符以"p"結(jié)尾,則以極坐標(biāo)的形式輸出向量,即"p"之前的部分做正常處理;如果沒有"p",則按笛卡爾坐標(biāo)形式輸出。為此,我們還需要一個(gè)計(jì)算弧度的方法angle

# 代碼7
class Vector2d:
    -- snip --
    
    def angle(self):
        return math.atan2(self.y, self.x)  # 弧度

    def __format__(self, format_spec=""):
        if format_spec.endswith("p"):
            format_spec = format_spec[:-1]
            coords = (abs(self), self.angle())
            outer_fmt = "<{}, {}>"
        else:
            coords = self
            outer_fmt = "({}, {})"
        components = (format(c, format_spec) for c in coords)
        return outer_fmt.format(*components)

以下是實(shí)際示例:

# 代碼8
>>> format(Vector2d(1, 1), "0.5fp")
"<1.41421, 0.78540>"
>>> format(Vector2d(1, 1), "0.5f")
"(1.00000, 1.00000)"
6. 可散列的Vector2d

關(guān)于可散列的概念可以參考之前的文章《Python學(xué)習(xí)之路22》。

目前的Vector2d是不可散列的,為此我們需要實(shí)現(xiàn)__hash__特殊方法,而在此之前,我們還要讓向量不可變,即self.xself.y的值不能被修改。之所以要讓向量不可變,是因?yàn)槲覀冊(cè)谟?jì)算向量的哈希值時(shí)需要用到self.xself.y的哈希值,如果這兩個(gè)值可變,那向量的哈希值就能隨時(shí)變化,這將不是一個(gè)可散列的對(duì)象。

補(bǔ)充

在文章《Python學(xué)習(xí)之路22》中說道,用戶自定義的對(duì)象默認(rèn)是可散列的,它的散列值等于id()的返回值。但是此處的Vector2d卻是不可散列的,這是為什么?其實(shí),如果我們要讓自定義類變?yōu)榭缮⒘械模_的做法是同時(shí)實(shí)現(xiàn)__hash____eq__這兩個(gè)特殊方法。當(dāng)這兩個(gè)方法都沒有重寫時(shí),自定義類的哈希值就是id()的返回值,此時(shí)自定義類可散列;當(dāng)我們只重寫了__hash__方法時(shí),自定義類也是可散列的,哈希值就是__hash__的返回值;但是,如果只重寫了__eq__方法,而沒有重寫__hash__方法,此時(shí)自定義類便不可散列。

這里再次給出可散列對(duì)象必須滿足的三個(gè)條件:

支持hash()函數(shù),并且通過__hash__方法所得到的哈希值是不變的;

支持通過__eq__方法來檢測(cè)相等性;

a == b為真,則hash(a) == hash(b)也必須為真。

根據(jù)官方文檔,最好使用異或運(yùn)算^混合各分量的哈希值,下面是Vector2d的改進(jìn):

# 代碼9
class Vector2d:
    -- snip --
    
    def __init__(self, x, y):
        self.__x = float(x)
        self.__y = float(y)

    @property  # 把方法變?yōu)閷傩哉{(diào)用,相當(dāng)于getter方法
    def x(self):
        return self.__x

    @property
    def y(self):
        return self.__y

    def __hash__(self):
        return hash(self.x) ^ hash(self.y)
    
    -- snip --

文章至此說的都是一些特殊方法,如果想到得到功能完善的對(duì)象,這些方法可能是必備的,但如果你的應(yīng)用用不到這些東西,則完全沒有必要去實(shí)現(xiàn)這些方法,客戶并不關(guān)心你的對(duì)象是否符合Python風(fēng)格。

Vector2d暫時(shí)告一段落,現(xiàn)在來說一說其它比較雜的內(nèi)容。

7. Python的私有屬性和"受保護(hù)的"屬性

Python不像C++、Java那樣可以用private關(guān)鍵字來創(chuàng)建私有屬性,但在Python中,可以以雙下劃線開頭來命名屬性以實(shí)現(xiàn)"私有"屬性,但是這種屬性會(huì)發(fā)生名稱改寫(name mangling):Python會(huì)在這樣的屬性前面加上一個(gè)下劃線和類名,然后再存入實(shí)例的__dict__屬性中,以最新的Vector2d為例:

# 代碼10
>>> v1 = Vector2d(1, 2)
>>> v1.__dict__
{"_Vector2d__x": 1.0, "_Vector2d__y": 2.0}

當(dāng)屬性以雙下劃線開頭時(shí),其實(shí)是告訴別的程序員,不要直接訪問這個(gè)屬性,它是私有的。名稱改寫的目的是避免意外訪問,而不能防止故意訪問。只要你知道規(guī)則,這些屬性一樣可以訪問。

還有以單下劃線開頭的屬性,這種屬性在Python的官方文檔的某個(gè)角落里被稱為了"受保護(hù)的"屬性,但Python不會(huì)對(duì)這種屬性做特殊處理,這只是一種約定俗成的規(guī)矩,告訴別的程序員不要試圖從外部訪問這些屬性。這種命名方式很常見,但其實(shí)很少有人把這種屬性叫做"受保護(hù)的"屬性。

還是那句話,Python中所有的屬性都是公有的,Python沒有不能訪問的屬性!這些規(guī)則并不能阻止你有意訪問這些屬性,一切都看你遵不遵守上面這些"不成文"的規(guī)則了。

8. 覆蓋類屬性

這里首先需要區(qū)分兩個(gè)概念,類屬性實(shí)例屬性

類屬性屬于整個(gè)類,該類的所有實(shí)例都能訪問這個(gè)屬性,可以動(dòng)態(tài)綁定類屬性,動(dòng)態(tài)綁定的類屬性所有實(shí)例也都可以訪問,即類屬性的作用域是整個(gè)類。可以按Vector2d中定義typecode的方式來定義類屬性,即直接在class中定義屬性,而不是在__init__中;

實(shí)例屬性只屬于某個(gè)實(shí)例對(duì)象,實(shí)例也能動(dòng)態(tài)綁定屬性。實(shí)例屬性只能這個(gè)實(shí)例自己訪問,即實(shí)例屬性的作用域是類對(duì)象作用域。實(shí)例屬性需要和self綁定,self指向的是實(shí)例,而不是類。

Python有個(gè)很獨(dú)特的特性:類屬性可用于為實(shí)例屬性提供默認(rèn)值

Vector2d中有個(gè)typecode類屬性,注意到,我們?cè)?b>__bytes__方法中通過self.typecode兩次用到了它,這里明明是通過self調(diào)用實(shí)例屬性,可Vector2d的實(shí)例并沒有這個(gè)屬性。self.typecode其實(shí)獲取的是Vector2d.typecode類屬性的值,而至于怎么從實(shí)例屬性跳到類屬性的,以后有機(jī)會(huì)多帶帶用一篇文章來講。

補(bǔ)充:證明實(shí)例沒有typecode屬性

# 代碼11
>>> v = Vector2d(1, 2)
>>> v.__dict__
{"_Vector2d__x": 1.0, "_Vector2d__y": 2.0} # 實(shí)例中并沒有typecode屬性

如果為不存在的實(shí)例屬性賦值,則會(huì)新建該實(shí)例屬性。假如我們?yōu)?b>typecode實(shí)例屬性賦值,同名類屬性不會(huì)受到影響,但會(huì)被實(shí)例屬性給覆蓋掉(類似于之前在函數(shù)閉包中講的局部變量和全局變量的區(qū)別)。借助這一特性,可以為各個(gè)實(shí)例的typecode屬性定制不同的值,比如在生成字節(jié)序列時(shí),將實(shí)例轉(zhuǎn)換成4字節(jié)的單精度浮點(diǎn)數(shù):

# 代碼12
>>> v1 = Vector2d(1.1, 2.2) 
>>> dumpd = bytes(v1) # 按雙精度轉(zhuǎn)換
>>> dumpd
b"dx9ax99x99x99x99x99xf1?x9ax99x99x99x99x99x01@"
>>> len(dumpd)
17
>>> v1.typecode = "f"
>>> dumpf = bytes(v1) # 按單精度轉(zhuǎn)換
>>> dumpf
b"fxcdxccx8c?xcdxccx0c@"  # 明白為什么要在字節(jié)序列前加上typecode的值了嗎?為了支持不同格式。
>>> len(dumpf)
9
>>> Vector2d.typecode
"d"

如果想要修改類屬性的值,必須直接在類上修改,不能通過實(shí)例修改。如果想修改所有實(shí)例的typecode屬性的默認(rèn)值,可以這么做:

# 代碼13
Vector2d.typecode = "f"

然而有種方式更符合Python風(fēng)格,而且效果持久,也更有針對(duì)性。通過繼承的方式修改類屬性,生成專門的子類。Django基于類的視圖就大量使用了這個(gè)技術(shù):

# 代碼14
>>> class ShortVector2d(Vector2d):
...     typecode = "f"   # 只修改這一處
...    
>>> sv = ShortVector2d(1/11, 1/27)
>>> sv
ShortVector2d(0.09090909090909091, 0.037037037037037035) # 沒有硬編碼class_name的原因
>>> len(bytes(sv))
9
9. __slots__類屬性

默認(rèn)情況下,Python在各個(gè)實(shí)例的__dict__屬性中以映射類型存儲(chǔ)實(shí)例屬性。正如《Python學(xué)習(xí)之路22》中所述,為了使用底層的散列表提升訪問速度,字典會(huì)消耗大量?jī)?nèi)存。如果要處理數(shù)百萬個(gè)屬性不多的實(shí)例,其實(shí)可以通過__slots__類屬性來節(jié)省大量?jī)?nèi)存。做法是讓解釋器用類似元組的結(jié)構(gòu)存儲(chǔ)實(shí)例屬性,而不是字典。

具體用法是,在類中創(chuàng)建這個(gè)__slots__類屬性,并把它的值設(shè)為一個(gè)可迭代對(duì)象,其中的元素是其余實(shí)例屬性的字符串表示。比如我們將之前定義的Vector2d改為__slots__版本:

# 代碼15
class Vector2d:
    __slots__ = ("__x", "__y")
    
    typecode = "d"  # 其余保持不變
    -- snip -- 

試驗(yàn)表明,創(chuàng)建一千萬個(gè)之前版本的Vector2d實(shí)例,內(nèi)存用量高達(dá)1.5GB,而__slots__版本的Vector2d的內(nèi)存用量不到700MB,并且速度也比之前的版本快。

__slots__也有一些需要注意的點(diǎn):

使用__slots__之后,實(shí)例不能再有__slots__中所列名稱之外的屬性,即,不能動(dòng)態(tài)添加屬性;如果要使其能動(dòng)態(tài)添加屬性,必須在其中加入"__dict__",但這么做又違背了初衷;

每個(gè)子類都要定義__slots__屬性,解釋器會(huì)忽略掉父類的__slots__屬性;

自定義類中默認(rèn)有__weakref__屬性,但如果定義了__slots__屬性,而且還要自定義類支持弱引用,則需要把"__weakref__"加入到__slots__中。

總之,不要濫用__slots__屬性,也不要用它來限制用戶動(dòng)態(tài)添加屬性(除非有意為之)。__slots__在處理列表數(shù)據(jù)時(shí)最有用,例如模式固定的數(shù)據(jù)庫(kù)記錄,以及特大型數(shù)據(jù)集。然而,當(dāng)遇到這類數(shù)據(jù)時(shí),更推薦使用Numpy和Pandas等第三方庫(kù)。

10. 總結(jié)

本篇首先按照一定的要求,定義了一個(gè)Vector2d類,重點(diǎn)是如果實(shí)現(xiàn)這個(gè)類的不同輸出形式;隨后,能從字節(jié)序列"反編譯"成我們需要的類,我們實(shí)現(xiàn)了一個(gè)備選構(gòu)造方法,順帶介紹了@classmethod@staticmethod裝飾器;接著,我們通過重寫__format_方法,實(shí)現(xiàn)了自定義格式化輸出數(shù)據(jù);然后,通過使用@property裝飾器,定義"私有"屬性以及重寫__hash__方法等操作實(shí)現(xiàn)了這個(gè)類的可散列化。至此,關(guān)于Vector2d的內(nèi)容基本結(jié)束。最后,我們介紹了兩種常見類型的屬性(“私有”,“保護(hù)”),覆蓋類屬性以及如何通過__slots__節(jié)省內(nèi)存等問題。

本文實(shí)現(xiàn)了這么多特殊方法只是為展示如何編寫標(biāo)準(zhǔn)Python對(duì)象的API,如果你的應(yīng)用用不到這些內(nèi)容,大可不必為了滿足Python風(fēng)格而給自己增加負(fù)擔(dān)。畢竟,簡(jiǎn)潔勝于復(fù)雜


迎大家關(guān)注我的微信公眾號(hào)"代碼港" & 個(gè)人網(wǎng)站 www.vpointer.net ~

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

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

相關(guān)文章

  • Python學(xué)習(xí)之路24-一等函數(shù)

    摘要:函數(shù)內(nèi)省的內(nèi)容到此結(jié)束。函數(shù)式編程并不是一個(gè)函數(shù)式編程語言,但通過和等包的支持,也可以寫出函數(shù)式風(fēng)格的代碼。 《流暢的Python》筆記。本篇主要講述Python中函數(shù)的進(jìn)階內(nèi)容。包括函數(shù)和對(duì)象的關(guān)系,函數(shù)內(nèi)省,Python中的函數(shù)式編程。 1. 前言 本片首先介紹函數(shù)和對(duì)象的關(guān)系;隨后介紹函數(shù)和可調(diào)用對(duì)象的關(guān)系,以及函數(shù)內(nèi)省。函數(shù)內(nèi)省這部分會(huì)涉及很多與IDE和框架相關(guān)的東西,如果平時(shí)...

    wind3110991 評(píng)論0 收藏0
  • Python學(xué)習(xí)之路20-數(shù)據(jù)模型

    摘要:前言數(shù)據(jù)模型其實(shí)是對(duì)框架的描述,它規(guī)范了這門語言自身構(gòu)件模塊的接口,這些模塊包括但不限于序列迭代器函數(shù)類和上下文管理器。上述類實(shí)現(xiàn)了方法,它可用于需要布爾值的上下文中等。但多虧了它是特殊方法,我們也可以把用于自定義數(shù)據(jù)類型。 《流暢的Python》筆記。本篇是Python進(jìn)階篇的開始。本篇主要是對(duì)Python特殊方法的概述。 1. 前言 數(shù)據(jù)模型其實(shí)是對(duì)Python框架的描述,它規(guī)范了...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<