2015-06-30 11 views
12

czytałem jakiś kod, który wyglądał w zasadzie tak:Czy "__module__" jest gwarantowane podczas tworzenia klasy?

class Foo(object): 
    class_name = __module__.replace('_', '-') 

do mnie, że wyglądała naprawdę dziwne (__module__, co to jest?), Więc poszedłem i spojrzał na pytona data-model. Szybkie wyszukiwanie pokazuje, że __module__ jest właściwością obiektów klasy i obiektów funkcji. Jednak w globalnej przestrzeni nazw nie ma dostępnego __module__ (można go łatwo sprawdzić, po prostu próbując na nie spojrzeć i obserwując, że wynik jest ...).

Postanowiłem przypisać to do konkretnego zachowania, ale jako ostatnią próbę zdecydowałem się przetestować z innymi wdrożeniami, które mam pod ręką. Okazuje się, że tego kodu z

  • CPython 2.7.6
  • CPython 3.4.0
  • jython 2.5.3
  • pypy 2,2,1 (Python 2.7.3)

Moje pytanie brzmi, czy to zachowanie jest faktycznie zdefiniowane w dowolnym miejscu w odnośniku do języka. Nie jestem pewien, dlaczego chciałbym, ale czy mogę bezpiecznie polegać na __module__ będąc w przestrzeni nazw tworzenia klas lub czy wszyscy implementatorzy po prostu decydują się zrobić to w ten sam sposób?

Wszystko linux, ale wątpię, że sprawy ...

+1

Nie można znaleźć niczego oprócz stanów [Python 2.3 * Co nowego *] (https://docs.python.org/2/whatsnew/2.3.html#build-and-c-api-changes) * Jeśli dynamicznie przydzielasz obiekty typu do swojego rozszerzenia, powinieneś wiedzieć o zmianie zasad dotyczących atrybutów "__module__" i "__name__". Podsumowując, będziesz chciał upewnić się, że słownik typu zawiera klucz "__module __"; tworząc nazwę modułu część nazwy typu prowadzącej do ostatniego okresu nie będzie już miała pożądanego efektu. Aby uzyskać więcej informacji, przeczytaj dokumentację referencyjną interfejsu API lub źródło. * –

+0

Ponieważ wydaje się, że wszyscy już to popierają, może być uzasadnione żądanie standaryzacji. – Veedrac

+0

@Veedrac - Nie zgadzam się tutaj. W języku Pythona jest dość dziwnie, że nazwiska pojawiają się tylko w twoim (nieglobalnym) obszarze nazw. na przykład Nie oczekuję, że pojawią się magiczne imiona, gdy stworzę funkcję ... – mgilson

Odpowiedz

8

Co dokumentacja zawiera definicji jest to, że zajęcia będą miały atrybut __module__. Wydaje się, że tak wygląda CPython, ponieważ definiuje lokalną zmienną __module__ na początku bloku klasy. Ta zmienna staje się następnie atrybutem klasy, jak każda inna zmienna tam zdefiniowana.

Nie mogę znaleźć żadnej dokumentacji mówiącej, że __module__ musi zostać zdefiniowany w ten sposób. W szczególności nie mogę znaleźć żadnej dokumentacji wyraźnie mówiąc, że atrybut musi być zdefiniowany jako zmienna lokalna w treści klasy, zamiast być przypisany jako atrybut klasy na pewnym późniejszym etapie tworzenia klasy. This answer na inne pytanie wspomina, że ​​działa w ten sposób i pokazuje, w jaki sposób pojawia się w kodzie bajtowym. Było a Jython bug, które naprawiono, czyniąc je działa tak jak CPython.

Zgaduję, że jest to szczegóły implementacji CPython, które zostały przeniesione do innych implementacji. O ile mogę powiedzieć, dokumentacja w rzeczywistości nie mówi, że __module__ musi być dostępny w treści klasy, a dopiero później w obiekcie klasy.

+1

Dokładnie; że nazwa jest tworzona jako pierwsza w treści klasy, nie jest gwarantowana w żadnym miejscu w specyfikacji języka. –

+0

To również było moje myślenie. W związku z tym doradziłem pierwotnym autorom kodu, aby zamiast tego polegali na globalnym pliku '__file__' (i różnych narzędziach w' os') - chociaż przypuszczam, że mógłbym im powiedzieć, żeby użyli '__name__' ... – mgilson

Powiązane problemy