<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          最全的命名元組Namedtuple使用指南?。?!

          共 11267字,需瀏覽 23分鐘

           ·

          2020-10-24 08:01

          ?△點(diǎn)擊上方Python貓”關(guān)注 ,回復(fù)“1”領(lǐng)取電子書

          劇照 | 《鬼滅之刃》

          譯者:DeanWu
          來源:碼農(nóng)吳先生

          原文地址:https://miguendes.me/everything-you-need-to-know-about-pythons-namedtuples

          作者:Miguel Brito

          本文將討論 python 中namedtuple的幾個重點(diǎn)用法。我們將由淺入深的介紹namedtuple的各概念。你將了解為什么使用它們,以及如何使用它們,從而使代碼更簡潔。

          在學(xué)習(xí)本指南之后,你一定會喜歡上使用它。

          學(xué)習(xí)目標(biāo)

          在本教程結(jié)束時,你應(yīng)該能夠:

          • 了解為什么以及何時使用Namedtuple
          • 將常規(guī)元組和字典轉(zhuǎn)換為Namedtuple
          • Namedtuple轉(zhuǎn)化為字典或常規(guī)元組
          • Namedtuple列表進(jìn)行排序
          • 了解Namedtuple和數(shù)據(jù)類(DataClass)之間的區(qū)別
          • 使用可選字段創(chuàng)建Namedtuple
          • Namedtuple序列化為 JSON
          • 添加文檔字符串(docstring)

          為什么要使用namedtuple?

          namedtuple是一個非常有趣(也被低估了)的數(shù)據(jù)結(jié)構(gòu)。我們可以輕松找到嚴(yán)重依賴常規(guī)元組和字典來存儲數(shù)據(jù)的 Python 代碼。我并不是說,這樣不好,只是有時候他們常常被濫用,且聽我慢慢道來。

          假設(shè)你有一個將字符串轉(zhuǎn)換為顏色的函數(shù)。顏色必須在 4 維空間 RGBA 中表示。

          def?convert_string_to_color(desc:?str,?alpha:?float?=?0.0):
          ????if?desc?==?"green":
          ????????return?50,?205,?50,?alpha
          ????elif?desc?==?"blue":
          ????????return?0,?0,?255,?alpha
          ????else:
          ????????return?0,?0,?0,?alpha

          然后,我們可以像這樣使用它:

          r,?g,?b,?a?=?convert_string_to_color(desc="blue",?alpha=1.0)

          好的,可以。但是我們這里有幾個問題。第一個是,無法確保返回值的順序。也就是說,沒有什么可以阻止其他開發(fā)者這樣調(diào)用

          convert_string_to_color:
          g,?b,?r,?a?=?convert_string_to_color(desc="blue",?alpha=1.0)

          另外,我們可能不知道該函數(shù)返回 4 個值,可能會這樣調(diào)用該函數(shù):

          r,?g,?b?=?convert_string_to_color(desc="blue",?alpha=1.0)

          于是,因?yàn)榉祷刂蒂x值失敗,拋出ValueError錯誤,調(diào)用失敗。

          確實(shí)如此。但是,你可能會問,為什么不使用字典呢?

          Python 的字典是一種非常通用的數(shù)據(jù)結(jié)構(gòu)。它們是一種存儲多個值的簡便方法。但是,字典并非沒有缺點(diǎn)。由于其靈活性,字典很容易被濫用。讓 我們看看使用字典之后的例子。

          def?convert_string_to_color(desc:?str,?alpha:?float?=?0.0):
          ????if?desc?==?"green":
          ????????return?{"r":?50,?"g":?205,?"b":?50,?"alpha":?alpha}
          ????elif?desc?==?"blue":
          ????????return?{"r":?0,?"g":?0,?"b":?255,?"alpha":?alpha}
          ????else:
          ????????return?{"r":?0,?"g":?0,?"b":?0,?"alpha":?alpha}

          好的,我們現(xiàn)在可以像這樣使用它,期望只返回一個值:

          color?=?convert_string_to_color(desc="blue",?alpha=1.0)

          無需記住順序,但它至少有兩個缺點(diǎn)。第一個是我們必須跟蹤密鑰的名稱。如果我們將其更改{"r": 0, “g”: 0, “b”: 0, “alpha”: alpha}{”red": 0, “green”: 0, “blue”: 0, “a”: alpha},則在訪問字段時會得到KeyError返回,因?yàn)殒Ir,g,balpha不再存在。

          字典的第二個問題是它們不可散列。這意味著我們無法將它們存儲在 set 或其他字典中。假設(shè)我們要跟蹤特定圖像有多少種顏色。如果我們使用collections.Counter計數(shù),我們將得到TypeError: unhashable type: ‘dict’。

          而且,字典是可變的,因此我們可以根據(jù)需要添加任意數(shù)量的新鍵。相信我,這是一些很難發(fā)現(xiàn)的令人討厭的錯誤點(diǎn)。

          好的,很好。那么現(xiàn)在怎么辦?我可以用什么代替呢?

          namedtuple!對,就是它!

          將我們的函數(shù)轉(zhuǎn)換為使用namedtuple

          from?collections?import?namedtuple
          ...
          Color?=?namedtuple("Color",?"r?g?b?alpha")
          ...
          def?convert_string_to_color(desc:?str,?alpha:?float?=?0.0):
          ????if?desc?==?"green":
          ????????return?Color(r=50,?g=205,?b=50,?alpha=alpha)
          ????elif?desc?==?"blue":
          ????????return?Color(r=50,?g=0,?b=255,?alpha=alpha)
          ????else:
          ????????return?Color(r=50,?g=0,?b=0,?alpha=alpha)

          與 dict 的情況一樣,我們可以將值分配給單個變量并根據(jù)需要使用。無需記住順序。而且,如果你使用的是諸如 PyCharm 和 VSCode 之類的 IDE ,還可以自動提示補(bǔ)全。

          color?=?convert_string_to_color(desc="blue",?alpha=1.0)
          ...
          has_alpha?=?color.alpha?>?0.0
          ...
          is_black?=?color.r?==?0?and?color.g?==?0?and?color.b?==?0

          最重要的是namedtuple是不可變的。如果團(tuán)隊中的另一位開發(fā)人員認(rèn)為在運(yùn)行時添加新字段是個好主意,則該程序?qū)箦e。

          >>>?blue?=?Color(r=0,?g=0,?b=255,?alpha=1.0)

          >>>?blue.e?=?0
          ---------------------------------------------------------------------------
          AttributeError????????????????????????????Traceback?(most?recent?call?last)
          -13-8c7f9b29c633>?in?
          ---->?1?blue.e?=?0

          AttributeError:?'Color'?object?has?no?attribute?'e'

          不僅如此,現(xiàn)在我們可以使用它 Counter 來跟蹤一個集合有多少種顏色。

          >>>?Counter([blue,?blue])
          >>>?Counter({Color(r=0,?g=0,?b=255,?alpha=1.0):?2})

          如何將常規(guī)元組或字典轉(zhuǎn)換為 namedtuple

          現(xiàn)在我們了解了為什么使用 namedtuple,現(xiàn)在該學(xué)習(xí)如何將常規(guī)元組和字典轉(zhuǎn)換為 namedtuple 了。假設(shè)由于某種原因,你有包含彩色 RGBA 值的字典實(shí)例。如果要將其轉(zhuǎn)換為Color namedtuple,則可以按以下步驟進(jìn)行:

          >>>?c?=?{"r":?50,?"g":?205,?"b":?50,?"alpha":?alpha}
          >>>?Color(**c)
          >>>?Color(r=50,?g=205,?b=50,?alpha=0)

          我們可以利用該**結(jié)構(gòu)將包解壓縮dictnamedtuple

          如果我想從 dict 創(chuàng)建一個 namedtupe,如何做?

          沒問題,下面這樣做就可以了:

          >>>?c?=?{"r":?50,?"g":?205,?"b":?50,?"alpha":?alpha}
          >>>?Color?=?namedtuple("Color",?c)
          >>>?Color(**c)
          Color(r=50,?g=205,?b=50,?alpha=0)

          通過將 dict 實(shí)例傳遞給 namedtuple 工廠函數(shù),它將為你創(chuàng)建字段。然后,Color 像上邊的例子一樣解壓字典 c,創(chuàng)建新實(shí)例。

          如何將 namedtuple 轉(zhuǎn)換為字典或常規(guī)元組

          我們剛剛學(xué)習(xí)了如何將轉(zhuǎn)換namedtupledict。反過來呢?我們又如何將其轉(zhuǎn)換為字典實(shí)例?

          實(shí)驗(yàn)證明,namedtuple 它帶有一種稱為的方法._asdict()。因此,轉(zhuǎn)換它就像調(diào)用方法一樣簡單。

          >>>?blue?=?Color(r=0,?g=0,?b=255,?alpha=1.0)
          >>>?blue._asdict()
          {'r':?0,?'g':?0,?'b':?255,?'alpha':?1.0}

          你可能想知道為什么該方法以_開頭。這是與 Python 的常規(guī)規(guī)范不一致的一個地方。通常,_代表私有方法或?qū)傩?。但是?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;">namedtuple為了避免命名沖突將它們添加到了公共方法中。除了_asdict,還有_replace,_fields_field_defaults。你可以在這里[1]找到所有這些。

          要將namedtupe轉(zhuǎn)換為常規(guī)元組,只需將其傳遞給 tuple 構(gòu)造函數(shù)即可。

          >>>?tuple(Color(r=50,?g=205,?b=50,?alpha=0.1))
          (50,?205,?50,?0.1)

          如何對 namedtuples 列表進(jìn)行排序

          另一個常見的用例是將多個namedtuple實(shí)例存儲在列表中,并根據(jù)某些條件對它們進(jìn)行排序。例如,假設(shè)我們有一個顏色列表,我們需要按 alpha 強(qiáng)度對其進(jìn)行排序。

          幸運(yùn)的是,Python 允許使用非常 Python 化的方式來執(zhí)行此操作。我們可以使用operator.attrgetter運(yùn)算符。根據(jù)文檔[2],attrgetter“返回從其操作數(shù)獲取 attr 的可調(diào)用對象”。簡單來說就是,我們可以通過該運(yùn)算符,來獲取傳遞給 sorted 函數(shù)排序的字段。例:

          from?operator?import?attrgetter
          ...
          colors?=?[
          ????Color(r=50,?g=205,?b=50,?alpha=0.1),
          ????Color(r=50,?g=205,?b=50,?alpha=0.5),
          ????Color(r=50,?g=0,?b=0,?alpha=0.3)
          ]
          ...
          >>>?sorted(colors,?key=attrgetter("alpha"))
          [Color(r=50,?g=205,?b=50,?alpha=0.1),
          ?Color(r=50,?g=0,?b=0,?alpha=0.3),
          ?Color(r=50,?g=205,?b=50,?alpha=0.5)]

          現(xiàn)在,顏色列表按 alpha 強(qiáng)度升序排列!

          如何將 namedtuples 序列化為 JSON

          有時你可能需要將儲存namedtuple轉(zhuǎn)為 JSON。Python 的字典可以通過 json 模塊轉(zhuǎn)換為 JSON。那么我們可以使用_asdict 方法將元組轉(zhuǎn)換為字典,然后接下來就和字典一樣了。例如:

          >>>?blue?=?Color(r=0,?g=0,?b=255,?alpha=1.0)
          >>>?import?json
          >>>?json.dumps(blue._asdict())
          '{"r":?0,?"g":?0,?"b":?255,?"alpha":?1.0}'

          如何給 namedtuple 添加 docstring

          在 Python 中,我們可以使用純字符串來記錄方法,類和模塊。然后,此字符串可作為名為的特殊屬性使用__doc__。話雖這么說,我們?nèi)绾蜗蛭覀兊?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;">Color namedtuple添加 docstring 的?

          我們可以通過兩種方式做到這一點(diǎn)。第一個(比較麻煩)是使用包裝器擴(kuò)展元組。這樣,我們便可以 docstring 在此包裝器中定義。例如,請考慮以下代碼片段:

          _Color?=?namedtuple("Color",?"r?g?b?alpha")

          class?Color(_Color):
          ????"""A?namedtuple?that?represents?a?color.
          ????It?has?4?fields:
          ????r?-?red
          ????g?-?green
          ????b?-?blue
          ????alpha?-?the?alpha?channel
          ????"
          ""

          >>>?print(Color.__doc__)
          A?namedtuple?that?represents?a?color.
          ????It?has?4?fields:
          ????r?-?red
          ????g?-?green
          ????b?-?blue
          ????alpha?-?the?alpha?channel
          >>>?help(Color)
          Help?on?class?Color?in?module?__main__:

          class?Color(Color)
          ?|??Color(r,?g,?b,?alpha)
          ?|
          ?|??A?namedtuple?that?represents?a?color.
          ?|??It?has?4?fields:
          ?|??r?-?red
          ?|??g?-?green
          ?|??b?-?blue
          ?|??alpha?-?the?alpha?channel
          ?|
          ?|??Method?resolution?order:
          ?|??????Color
          ?|??????Color
          ?|??????builtins.tuple
          ?|??????builtins.object
          ?|
          ?|??Data?descriptors?defined?here:
          ?|
          ?|??__dict__
          ?|??????dictionary?for?instance?variables?(if?defined)

          如上,通過繼承_Color元組,我們?yōu)?namedtupe 添加了一個__doc__屬性。

          添加的第二種方法,直接設(shè)置__doc__屬性。這種方法不需要擴(kuò)展元組。

          >>>?Color.__doc__?=?"""A?namedtuple?that?represents?a?color.
          ????It?has?4?fields:
          ????r?-?red
          ????g?-?green
          ????b?-?blue
          ????alpha?-?the?alpha?channel
          ????"""

          注意,這些方法僅適用于Python 3+。

          namedtuples 和數(shù)據(jù)類(Data Class)之間有什么區(qū)別?

          功能

          在 Python 3.7 之前,可使用以下任一方法創(chuàng)建一個簡單的數(shù)據(jù)容器:

          • namedtuple
          • 常規(guī)類
          • 第三方庫,attrs

          如果你想使用常規(guī)類,那意味著你將必須實(shí)現(xiàn)幾個方法。例如,常規(guī)類將需要一種__init__方法來在類實(shí)例化期間設(shè)置屬性。如果你希望該類是可哈希的,則意味著自己實(shí)現(xiàn)一個__hash__方法。為了比較不同的對象,還需要__eq__實(shí)現(xiàn)一個方法。最后,為了簡化調(diào)試,你需要一種__repr__方法。

          讓我們使用常規(guī)類來實(shí)現(xiàn)下我們的顏色用例。

          class?Color:
          ????"""A?regular?class?that?represents?a?color."""

          ????def?__init__(self,?r,?g,?b,?alpha=0.0):
          ????????self.r?=?r
          ????????self.g?=?g
          ????????self.b?=?b
          ????????self.alpha?=?alpha

          ????def?__hash__(self):
          ????????return?hash((self.r,?self.g,?self.b,?self.alpha))

          ????def?__repr__(self):
          ????????return?"{0}({1},?{2},?{3},?{4})".format(
          ????????????self.__class__.__name__,?self.r,?self.g,?self.b,?self.alpha
          ????????)

          ????def?__eq__(self,?other):
          ????????if?not?isinstance(other,?Color):
          ????????????return?False
          ????????return?(
          ????????????self.r?==?other.r
          ????????????and?self.g?==?other.g
          ????????????and?self.b?==?other.b
          ????????????and?self.alpha?==?other.alpha
          ????????)

          如上,你需要實(shí)現(xiàn)好多方法。你只需要一個容器來為你保存數(shù)據(jù),而不必?fù)?dān)心分散注意力的細(xì)節(jié)。同樣,人們偏愛實(shí)現(xiàn)類的一個關(guān)鍵區(qū)別是常規(guī)類是可變的。

          實(shí)際上,引入數(shù)據(jù)類(Data Class)PEP[3]將它們稱為“具有默認(rèn)值的可變 namedtuple”(譯者注:Data Class python 3.7 引入,參考:https://docs.python.org/zh-cn/3/library/dataclasses.html)。

          現(xiàn)在,讓我們看看如何用數(shù)據(jù)類來實(shí)現(xiàn)。

          from?dataclasses?import?dataclass
          ...
          @dataclass
          class?Color:
          ????"""A?regular?class?that?represents?a?color."""
          ????r:?float
          ????g:?float
          ????b:?float
          ????alpha:?float

          哇!就是這么簡單。由于沒有__init__,你只需在 docstring 后面定義屬性即可。此外,必須使用類型提示對其進(jìn)行注釋。

          除了可變之外,數(shù)據(jù)類還可以開箱即用提供可選字段。假設(shè)我們的 Color 類不需要 alpha 字段。然后我們可以設(shè)置為可選。

          from?dataclasses?import?dataclass
          from?typing?import?Optional
          ...
          @dataclass
          class?Color:
          ????"""A?regular?class?that?represents?a?color."""
          ????r:?float
          ????g:?float
          ????b:?float
          ????alpha:?Optional[float]

          我們可以像這樣實(shí)例化它:

          >>> blue = Color(r=0, g=0, b=255)

          由于它們是可變的,因此我們可以更改所需的任何字段。我們可以像這樣實(shí)例化它:

          >>>?blue?=?Color(r=0,?g=0,?b=255)
          >>>?blue.r?=?1
          >>>?#?可以設(shè)置更多的屬性字段
          >>>?blue.e?=?10

          相較之下,namedtuple默認(rèn)情況下沒有可選字段。要添加它們,我們需要一點(diǎn)技巧和一些元編程。

          提示:要添加__hash__方法,你需要通過將設(shè)置unsafe_hash為使其不可變True

          @dataclass(unsafe_hash=True)
          class?Color:
          ????...

          另一個區(qū)別是,拆箱(unpacking)是 namedtuples 的自帶的功能(first-class citizen)。如果希望數(shù)據(jù)類具有相同的行為,則必須實(shí)現(xiàn)自己。

          from?dataclasses?import?dataclass,?astuple
          ...
          @dataclass
          class?Color:
          ????"""A?regular?class?that?represents?a?color."""
          ????r:?float
          ????g:?float
          ????b:?float
          ????alpha:?float

          ????def?__iter__(self):
          ????????yield?from?dataclasses.astuple(self)

          性能比較

          僅比較功能是不夠的,namedtuple 和數(shù)據(jù)類在性能上也有所不同。數(shù)據(jù)類基于純 Python 實(shí)現(xiàn) dict。這使得它們在訪問字段時更快。另一方面,namedtuples 只是常規(guī)的擴(kuò)展 tuple。這意味著它們的實(shí)現(xiàn)基于更快的 C 代碼并具有較小的內(nèi)存占用量。

          為了證明這一點(diǎn),請考慮在 Python 3.8.5 上進(jìn)行此實(shí)驗(yàn)。

          In?[6]:?import?sys

          In?[7]:?ColorTuple?=?namedtuple("Color",?"r?g?b?alpha")

          In?[8]:?@dataclass
          ???...:?class?ColorClass:
          ???...:?????"""A?regular?class?that?represents?a?color."""
          ???...:?????r:?float
          ???...:?????g:?float
          ???...:?????b:?float
          ???...:?????alpha:?float
          ???...:

          In?[9]:?color_tup?=?ColorTuple(r=50,?g=205,?b=50,?alpha=1.0)

          In?[10]:?color_cls?=?ColorClass(r=50,?g=205,?b=50,?alpha=1.0)

          In?[11]:?%timeit?color_tup.r
          36.8?ns?±?0.109?ns?per?loop?(mean?±?std.?dev.?of?7?runs,?10000000?loops?each)

          In?[12]:?%timeit?color_cls.r
          38.4?ns?±?0.112?ns?per?loop?(mean?±?std.?dev.?of?7?runs,?10000000?loops?each)

          In?[15]:?sys.getsizeof(color_tup)
          Out[15]:?72

          In?[16]:?sys.getsizeof(color_cls)?+?sys.getsizeof(vars(color_cls))
          Out[16]:?152

          如上,數(shù)據(jù)類在中訪問字段的速度稍快一些,但是它們比 nametuple 占用更多的內(nèi)存空間。

          如何將類型提示添加到 namedtuple

          數(shù)據(jù)類默認(rèn)使用類型提示。我們也可以將它們放在 namedtuples 上。通過導(dǎo)入 Namedtuple 注釋類型并從中繼承,我們可以對 Color 元組進(jìn)行注釋。

          from?typing?import?NamedTuple
          ...
          class?Color(NamedTuple):
          ????"""A?namedtuple?that?represents?a?color."""
          ????r:?float
          ????g:?float
          ????b:?float
          ????alpha:?float

          另一個可能未引起注意的細(xì)節(jié)是,這種方式還允許我們使用 docstring。如果輸入,help(Color)我們將能夠看到它們。

          Help?on?class?Color?in?module?__main__:

          class?Color(builtins.tuple)
          ?|??Color(r:?float,?g:?float,?b:?float,?alpha:?Union[float,?NoneType])
          ?|
          ?|??A?namedtuple?that?represents?a?color.
          ?|
          ?|??Method?resolution?order:

          ?|??????Color
          ?|??????builtins.tuple
          ?|??????builtins.object
          ?|
          ?|??Methods?defined?here:
          ?|
          ?|??__getnewargs__(self)
          ?|??????Return?self?as?a?plain?tuple.??Used?by?copy?and?pickle.
          ?|
          ?|??__repr__(self)
          ?|??????Return?a?nicely?formatted?representation?string
          ?|
          ?|??_asdict(self)
          ?|??????Return?a?new?dict?which?maps?field?names?to?their?values.

          如何將可選的默認(rèn)值添加到 namedtuple

          在上一節(jié)中,我們了解了數(shù)據(jù)類可以具有可選值。另外,我提到要模仿上的相同行為,namedtuple需要進(jìn)行一些技巧修改操作。事實(shí)證明,我們可以使用繼承,如下例所示。

          from?collections?import?namedtuple

          class?Color(namedtuple("Color",?"r?g?b?alpha")):
          ????__slots__?=?()
          ????def?__new__(cls,?r,?g,?b,?alpha=None):
          ????????return?super().__new__(cls,?r,?g,?b,?alpha)
          >>>?c?=?Color(r=0,?g=0,?b=0)
          >>>?c
          Color(r=0,?g=0,?b=0,?alpha=None)

          結(jié)論

          元組是一個非常強(qiáng)大的數(shù)據(jù)結(jié)構(gòu)。它們使我們的代碼更清潔,更可靠。盡管與新的數(shù)據(jù)類競爭激烈,但他們?nèi)杂写罅康膱鼍翱捎?。在本教程中,我們學(xué)習(xí)了使用namedtuples的幾種方法,希望你可以使用它們。

          參考資料

          [1]

          這里: https://docs.python.org/3/library/collections.html#collections.somenamedtuple._asdict

          [2]

          文檔: https://docs.python.org/3/library/operator.html#operator.attrgetter

          [3]

          PEP: https://www.python.org/dev/peps/pep-0557/#abstract

          Python貓技術(shù)交流群開放啦!群里既有國內(nèi)一二線大廠在職員工,也有國內(nèi)外高校在讀學(xué)生,既有十多年碼齡的編程老鳥,也有中小學(xué)剛剛?cè)腴T的新人,學(xué)習(xí)氛圍良好!想入群的同學(xué),請在公號內(nèi)回復(fù)『交流群』,獲取貓哥的微信(謝絕廣告黨,非誠勿擾?。?/span>~

          近期熱門文章推薦:

          耗時兩年,我終于出了一本電子書!

          為什么說 Python 內(nèi)置函數(shù)并不是萬能的?

          Python 函數(shù)為什么會默認(rèn)返回 None?

          一篇文章掌握 Python 內(nèi)置 zip() 的全部內(nèi)容

          感謝創(chuàng)作者的好文
          瀏覽 168
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜无码福利 | 免费直接观看黄色网页 | 国产传媒无码 | 黄色电影av网站 黄色黄色1级a片 黄色免费日本欧美 | 999色色色 |