久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

參數解包使用迭代還是獲取項目?

Does argument unpacking use iteration or item-getting?(參數解包使用迭代還是獲取項目?)
本文介紹了參數解包使用迭代還是獲取項目?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我使用的是 Python 2.7.3.

I'm using Python 2.7.3.

考慮一個具有自定義(盡管很糟糕)迭代和獲取項目行為的虛擬類:

Consider a dummy class with custom (albeit bad) iteration and item-getting behavior:

class FooList(list):
    def __iter__(self):
        return iter(self)
    def next(self):
        return 3
    def __getitem__(self, idx):
        return 3

舉個例子,看看奇怪的行為:

Make an example and see the weird behavior:

>>> zz = FooList([1,2,3])

>>> [x for x in zz]
# Hangs because of the self-reference in `__iter__`.

>>> zz[0]
3

>>> zz[1]
3

但是現在,讓我們創建一個函數,然后對 zz 進行參數解包:

But now, let's make a function and then do argument unpacking on zz:

def add3(a, b, c):
    return a + b + c

>>> add3(*zz)
6
# I expected either 9 or for the interpreter to hang like the comprehension!

因此,參數解包是以某種方式從 zz 獲取項目數據,但不是通過使用其實現的迭代器迭代對象,也不是通過執行窮人的迭代器并調用 __getitem__ 與對象一樣多的項目.

So, argument unpacking is somehow getting the item data from zz but not by either iterating over the object with its implemented iterator and also not by doing a poor man's iterator and calling __getitem__ for as many items as the object has.

那么問題來了:add3(*zz)這個語法如果不是通過這些方法是如何獲取zz的數據成員的呢?我只是錯過了從這種類型獲取數據成員的另一種常見模式嗎?

So the question is: how does the syntax add3(*zz) acquire the data members of zz if not by these methods? Am I just missing one other common pattern for getting data members from a type like this?

我的目標是看看我是否可以編寫一個實現迭代或獲取項目的類,以改變參數解包語法對該類的含義.在嘗試了上面的兩個示例之后,我現在想知道參數解包如何獲取基礎數據以及程序員是否可以影響該行為.為此,Google 只返回了大量結果,解釋了 *args 語法的基本用法.

My goal is to see if I could write a class that implements iteration or item-getting in such a way that it changes what the argument unpacking syntax means for that class. After trying the two example above, I'm now wondering how argument unpacking gets at the underlying data and whether the programmer can influence that behavior. Google for this only gave back a sea of results explaining the basic usage of the *args syntax.

我沒有需要這樣做的用例,我并不是說這是一個好主意.出于好奇,我只是想看看怎么做.

I don't have a use case for needing to do this and I am not claiming it is a good idea. I just want to see how to do it for the sake of curiosity.

已添加

由于內置類型被特殊處理,這里有一個 object 示例,我只維護一個列表對象并實現我自己的獲取和設置行為來模擬列表.

Since the built-in types are treated specially, here's an example with object where I just maintain a list object and implement my own get and set behavior to emulate list.

class FooList(object):
    def __init__(self, lst):
        self.lst = lst
    def __iter__(self): raise ValueError
    def next(self): return 3
    def __getitem__(self, idx): return self.lst.__getitem__(idx)
    def __setitem__(self, idx, itm): self.lst.__setitem__(idx, itm)

在這種情況下,

In [234]: zz = FooList([1,2,3])

In [235]: [x for x in zz]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-235-ad3bb7659c84> in <module>()
----> 1 [x for x in zz]

<ipython-input-233-dc9284300db1> in __iter__(self)
      2     def __init__(self, lst):
      3         self.lst = lst
----> 4     def __iter__(self): raise ValueError
      5     def next(self): return 3
      6     def __getitem__(self, idx): return self.lst.__getitem__(idx)

ValueError:

In [236]: add_3(*zz)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-236-f9bbfdc2de5c> in <module>()
----> 1 add_3(*zz)

<ipython-input-233-dc9284300db1> in __iter__(self)
      2     def __init__(self, lst):
      3         self.lst = lst
----> 4     def __iter__(self): raise ValueError
      5     def next(self): return 3
      6     def __getitem__(self, idx): return self.lst.__getitem__(idx)

ValueError:

但是,如果我確保迭代停止并始終返回 3,我可以在第一種情況下得到我正在拍攝的東西:

But instead, if I ensure iteration stops and always returns 3, I can get what I was shooting to play around with in the first case:

class FooList(object):
    def __init__(self, lst):
        self.lst = lst
        self.iter_loc = -1
    def __iter__(self): return self
    def next(self): 
        if self.iter_loc < len(self.lst)-1:
            self.iter_loc += 1
            return 3
        else:
            self.iter_loc = -1
            raise StopIteration
    def __getitem__(self, idx): return self.lst.__getitem__(idx)
    def __setitem__(self, idx, itm): self.lst.__setitem__(idx, itm)

然后我看到了這個,這正是我最初所期望的:

Then I see this, which is what I originally expected:

In [247]: zz = FooList([1,2,3])

In [248]: ix = iter(zz)

In [249]: ix.next()
Out[249]: 3

In [250]: ix.next()
Out[250]: 3

In [251]: ix.next()
Out[251]: 3

In [252]: ix.next()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-252-29d4ae900c28> in <module>()
----> 1 ix.next()

<ipython-input-246-5479fdc9217b> in next(self)
     10         else:
     11             self.iter_loc = -1
---> 12             raise StopIteration
     13     def __getitem__(self, idx): return self.lst.__getitem__(idx)
     14     def __setitem__(self, idx, itm): self.lst.__setitem__(idx, itm)

StopIteration:

In [253]: ix = iter(zz)

In [254]: ix.next()
Out[254]: 3

In [255]: ix.next()
Out[255]: 3

In [256]: ix.next()
Out[256]: 3

In [257]: ix.next()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-257-29d4ae900c28> in <module>()
----> 1 ix.next()

<ipython-input-246-5479fdc9217b> in next(self)
     10         else:
     11             self.iter_loc = -1
---> 12             raise StopIteration
     13     def __getitem__(self, idx): return self.lst.__getitem__(idx)
     14     def __setitem__(self, idx, itm): self.lst.__setitem__(idx, itm)

StopIteration:

In [258]: add_3(*zz)
Out[258]: 9

In [259]: zz[0]
Out[259]: 1

In [260]: zz[1]
Out[260]: 2

In [261]: zz[2]
Out[261]: 3

In [262]: [x for x in zz]
Out[262]: [3, 3, 3]

總結

  1. 語法 *args 僅依賴于迭代.對于內置類型,這種情況在繼承自內置類型的類中無法直接覆蓋.

  1. The syntax *args relies on iteration only. For built-in types this happens in a way that is not directly overrideable in classes that inherit from the built-in type.

這兩個在功能上是等價的:

These two are functionally equivalent:

foo(*[x for x in args])

foo(*args)

即使對于有限的數據結構,這些也不等價.

These are not equivalent even for finite data structures.

foo(*args)

foo(*[args[i] for i in range(len(args))])

推薦答案

你已經被 Python 最惱人的疣之一咬了:內置類型和它們的子類在某些地方被神奇地對待.

You have been bitten by one of Python's most irritating warts: builtin types and subclasses of them are treated magically in some places.

由于您的類型是 list 的子類,Python 神奇地進入了它的內部來解包它.它根本不使用真正的迭代器 API.如果您在 next__getitem__ 中插入 print 語句,您將看到沒有一個被調用.此行為不能被覆蓋;相反,您必須編寫自己的類來重新實現內置類型.您可以嘗試使用 UserList;我還沒有檢查這是否可行.

Since your type subclasses from list, Python magically reaches into its internals to unpack it. It doesn't use the real iterator API at all. If you insert print statements inside your next and __getitem__, you'll see that neither one is being called. This behavior cannot be overridden; instead, you would have to write your own class that reimplements the builtin types. You could try using UserList; I haven't checked whether that would work.

您的問題的答案是參數解包使用迭代.但是,如果沒有明確定義 __iter__,迭代本身可以使用 __getitem__.您不能創建一個定義與正常迭代行為不同的參數解包行為的類.

The answer to your question is that argument unpacking uses iteration. However, iteration itself can use __getitem__ if there is no explicit __iter__ defined. You can't make a class that defines argument-unpacking behavior that is different from the normal iteration behavior.

不應假定迭代器協議(基本上是__iter__ 的工作原理")適用于像 list 這樣的子類內置類型的類型.如果你繼承一個內置函數,你的子類在某些情況下可能會神奇地表現得像底層內置函數,而不使用你自定義的魔法方法(如 __iter__).如果您想完全可靠地自定義行為,則不能從內置類型子類化(當然,object 除外).

The iterator protocol (basically "how __iter__ works") shouldn't be assumed to apply to types that subclass builtin types like list. If you subclass a builtin, your subclass may magically behave like the underlying builtin in certain situations, without making use of your customize magic methods (like __iter__). If you want to customize behavior fully and reliably, you can't subclass from builtin types (except, of course, object).

這篇關于參數解包使用迭代還是獲取項目?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How to draw a rectangle around a region of interest in python(如何在python中的感興趣區域周圍繪制一個矩形)
How can I detect and track people using OpenCV?(如何使用 OpenCV 檢測和跟蹤人員?)
How to apply threshold within multiple rectangular bounding boxes in an image?(如何在圖像的多個矩形邊界框中應用閾值?)
How can I download a specific part of Coco Dataset?(如何下載 Coco Dataset 的特定部分?)
Detect image orientation angle based on text direction(根據文本方向檢測圖像方向角度)
Detect centre and angle of rectangles in an image using Opencv(使用 Opencv 檢測圖像中矩形的中心和角度)
主站蜘蛛池模板: 欧美日韩中文字幕在线播放 | 狠狠插天天干 | 亚洲精品中文字幕在线 | 久热久热| 欧美专区在线观看 | 成人动漫一区二区 | 91高清在线观看 | 久久九 | 午夜小视频在线播放 | 四虎永久免费影院 | 91精品麻豆日日躁夜夜躁 | 国产精品久久久久久久久免费桃花 | 99色在线| 激情婷婷| 免费视频二区 | 九九热这里只有精品6 | 国产精品一区二区在线观看 | 日韩伦理一区二区 | 亚洲一一在线 | 欧洲妇女成人淫片aaa视频 | 在线国产视频 | 欧美videosex性极品hd | 国产精品久久久久久av公交车 | 天天综合久久网 | 日本中文字幕一区 | 精品视频久久久久久 | 国产欧美日韩在线观看 | 毛片网站免费观看 | 国产视频第一页 | 午夜影院黄 | 午夜精品一区二区三区免费视频 | 99re在线视频观看 | 欧美日韩在线视频一区二区 | 精品欧美一区二区在线观看视频 | 国产粉嫩尤物极品99综合精品 | 在线视频日韩 | 中国一级特黄真人毛片免费观看 | 久久一级大片 | 亚洲成人一级 | 精品国产aⅴ| 日本一区二区不卡视频 |