Bir Python nesnesinin “abonelenebilir” olup olmadığı ne anlama gelir?


Yanıtlar:


356

Temel olarak nesnenin __getitem__()yöntemi uyguladığı anlamına gelir . Başka bir deyişle, "kapsayıcı" olan nesneleri, yani başka nesneleri içerdiklerini açıklar. Buna dizeler, listeler, tuples ve sözlükler dahildir.


2
Ne kadar güvenilir: hasattr(SomeClassWithoutGetItem, '__getitem__')bir şeyin abonelenebilir olup olmadığını belirlemek için?
jmunsch

2
[... ]indeksleme sözdizimi bir denir simge o matematiksel gösterime eşdeğer, çünkü kullanımları fiili simgeler olduğunu; Örneğin a[1]matematikçilerin a₁ olarak yazacakları için Python . Yani "abone olunabilir", "abone olunabilir" anlamına gelir. Ki, Python açısından, bu uygulamaya sahip demektir __getitem__(), çünkü a[1]sadece sözdizimsel şeker a.__getitem__(1).
Mark Reed

Bu çağrının hasattriyi çalışması gerekir, ancak bir şeyler yapmanın Pitonik yolu değildir; Python uygulaması Duck Typing'i teşvik eder . Yani, bir alt simge kullanarak nesnenizden bir öğe almaya çalışmayı planlıyorsanız, devam edin ve yapın; Nesne abone edilemediğinden işe yaramayabileceğini düşünüyorsanız, tryile bir blokta sarın except TypeError.
Mark Reed

77

Başımın üst kısmında, abone olunabilen tek yerleşik öğeler şunlardır:

string:  "foobar"[3] == "b"
tuple:   (1,2,3,4)[3] == 4
list:    [1,2,3,4][3] == 4
dict:    {"a":1, "b":2, "c":3}["c"] == 3

Ancak mipadi'nin cevabı doğrudur - uygulayan herhangi bir sınıf __getitem__aboneliklidir


17

Komut dosyası yazılabilir nesne, kendisine yapılan işlemleri kaydeden bir nesnedir ve bunları yeniden oynatılabilen bir "komut dosyası" olarak depolayabilir.

Örneğin, bkz. Uygulama Komut Dosyası Çerçevesi

Şimdi, eğer Alistair ne istediğini bilmiyorsa ve gerçekten "abonelikli" nesneler demek isterse (başkaları tarafından düzenlendiği gibi), o zaman (mipadi'nin de cevapladığı gibi) bu doğru olanıdır:

Abone olabilen bir nesne, __getitem__özel yöntemi (düşünme listeleri, sözlükler) uygulayan herhangi bir nesnedir .


2
Alistair tarafından değil, diğerleri tarafından düzenlendiği gibi "abone olunabilir" değil, "yazılabilir" nesneler hakkındaki orijinal soruyu yanıtladığımı unutmayın. Gerçekten Alistair'in yorum yapmasını istiyorum.
tzot

Ah, koleksiyonum için yeni bir rozet! :) Şaka yapıyordum, belli ki. Sorunun düzenlenmesini haklı kılan tek şey, Alistair'in bir cevap seçmesiydi; Alistair'in seçim konusunda emin olup olmadığından hala emin değilim.
tzot

16

Bilgi işlemdeki alt simge anlamı: "bir programın tek başına veya başkalarıyla birlikte bir dizinin öğelerinden birini belirtmek için kullanılan bir simge (zaman zaman alt simge olarak yazılır ancak uygulamada genellikle kullanılmaz)."

Şimdi, @ user2194711 tarafından verilen basit örnekte , ekleme öğesinin iki nedenden dolayı listenin bir parçası olamayacağını görebiliriz: -

1) Yönteme ekleme işlemini gerçekten çağırmıyoruz; çünkü onu ()çağırması gerekiyor.

2) Hata, işlevin veya yöntemin abone edilemediğini gösterir; bir liste veya sıra gibi dizine eklenemedikleri anlamına gelir.

Şimdi şuna bakın: -

>>> var = "myString"
>>> def foo(): return 0
... 
>>> var[3]
't'
>>> foo[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable

Bu, herhangi bir abonelik veya functiondizideki öğelerin sıralı olarak meydana geldiği anlamına gelir ; ve onların yardımıyla bizim gibi erişemeyiz [].

Ayrıca; mipadi'nin cevabında söylediği gibi ; Temel olarak nesnenin __getitem__()yöntemi uyguladığı anlamına gelir . (aboneliğiniz varsa). Böylece üretilen hata:

arr.append["HI"]

TypeError: 'builtin_function_or_method' nesnesi abone edilemez


7

Ben de aynı sorunu yaşadım. yapıyordum

arr = []
arr.append["HI"]

Yani kullanmak [hataya neden oluyordu. Olmalıarr.append("HI")


3

Buradaki önceki yanıtların bir sonucu olarak, çoğu zaman bu, olmadığınızda bir listeniz (veya dikteniz veya başka bir abonelik nesnesi) olduğunu düşündüğünüzün bir işaretidir.

Örneğin, bir liste döndürmesi gereken bir fonksiyonunuz olduğunu varsayalım ;

def gimme_things():
    if something_happens():
        return ['all', 'the', 'things']

Şimdi bu işlevi çağırdığınızda ve something_happens()bir nedenden dolayı bir Truedeğer döndürmediğinizde ne olur? ifEğer aracılığıyla düşmek böylece başarısız olur ve; gimme_thingsaçıkça returnhiçbir şey yapmaz - o zaman aslında, dolaylı olarak olacaktır return None. Sonra bu kod:

things = gimme_things()
print("My first thing is {0}".format(things[0]))

başarısız olur NoneType"çünkü iyi, nesne İndislenebilir değil" thingsise Noneve siz yapmaya çalışıyoruz bu yüzden None[0]hata mesajı ne diyor çünkü ... mantıklı değil hangi.

Kodunuzdaki bu hatayı düzeltmenin iki yolu vardır - birincisi, thingskullanmaya başlamadan önce aslında geçerli olup olmadığını kontrol ederek hatayı önlemektir ;

things = gimme_things()
if things:
    print("My first thing is {0}".format(things[0]))
else:
    print("No things")  # or raise an error, or do nothing, or ...

veya TypeErroristisnayı eşit olarak tuzağa düşürmek ;

things = gimme_things()
try:
    print("My first thing is {0}".format(things[0]))
except TypeError:
    print("No things")  # or raise an error, or do nothing, or ...

Bir diğeri, gimme_thingsher zaman bir liste döndürdüğünden emin olmak için yeniden tasarlamaktır . Bu durumda, muhtemelen daha basit bir tasarımdır, çünkü benzer bir hatanın olduğu birçok yer varsa, basit ve deyimsel tutulabilir.

def gimme_things():
    if something_happens():
        return ['all', 'the', 'things']
    else:  # make sure we always return a list, no matter what!
        logging.info("Something didn't happen; return empty list")
        return []

Tabii ki, else:şubeye koyduğunuz şey kullanım durumunuza bağlıdır. Belki bir something_happens()şeylerin yanlış gittiğini daha açık ve net hale getirmek için başarısız olduğunda bir istisna ortaya koymalısınız? Kendi kodunuza istisnalar eklemek, bir şey başarısız olduğunda neyin olduğunu tam olarak bilmenin önemli bir yoludur!

(Ayrıca, bu ikinci düzeltmenin hatayı nasıl tamamen düzeltmediğine de dikkat edin - abone olmaya çalışmanızı engeller None ama things[0]bir hala IndexErrorzaman thingsboş bir listedir Eğer bir varsa. tryYapabileceğiniz except (TypeError, IndexError)de tuzağa bunu için.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.