Birisi Python __all__ açıklayabilir misiniz?

oy
608

Ben daha Python kullanıyorum ve ben değişken görmeye devam __all__farklı yılında seti __init__.pydosyaları. Birisi bu ne açıklayabilir?

Oluştur 04/09/2008 saat 22:28
kaynak kullanıcı
Diğer dillerde...                            


11 cevaplar

oy
659

Bağlı, fakat burada açıkça belirtilmeyen, ne zaman tam olarak __all__kullanılır. Bu zaman ihraç edilecek bir modülde neler sembolleri tanımlayan dizeleri listesidir from <module> import *modül kullanılır.

Örneğin, bir de şu kod foo.pyaçıkça sembolleri ihraç barve baz:

__all__ = ['bar', 'baz']

waz = 5
bar = 10
def baz(): return 'baz'

Bu semboller daha sonra şöyle alınabilir:

from foo import *

print bar
print baz

# The following will trigger an exception, as "waz" is not exported by the module
print waz

Eğer __all__yukarıda dışarı yorum varsayılan davranışı olarak, bu kod, sonra tamamlanma çalıştırır import *verilen ad alanından, bir alt çizgi ile başlar olmayan tüm sembolleri içe aktarmaktır.

Referans: https://docs.python.org/3.5/tutorial/modules.html#importing-from-a-package

NOT: __all__ etkiler from <module> import *sadece davranış. Belirtilmeyen üyeleri __all__hala modül dışından erişilebilir ve birlikte alınabilir from <module> import <member>.

Cevap 15/09/2008 saat 16:49
kaynak kullanıcı

oy
305

Tarafından yorumlandığı gibi, bu modülün kamu nesnelerin bir listesi import *. Bu alt çizgiyle başlayan herşeyi gizleme varsayılan geçersiz kılar.

Cevap 04/09/2008 saat 22:30
kaynak kullanıcı

oy
130

Sadece bu hassas olmak ekliyorum:

Diğer tüm cevaplar bakın modüllerin . Orijinal soru explicitely sözü __all__de __init__.pydosyalar, bu nedenle bu piton hakkındadır paketleri .

Genellikle, __all__yalnızca devreye girer from xxx import *ve varyant importdeyimi kullanılır. Bu paketlere yanı sıra modüllerin için de geçerlidir.

Modülleri için davranış diğer cevaplar açıklanmıştır. Paketler için kesin davranış açıklanmıştır burada ayrıntılı olarak.

Kısacası, __all__bu ilgilenir dışında paket düzeyinde, yaklaşık modülleri için aynı şeyi yapar paket içinde modüllerin (belirterek aksine modülü içinde isimleri ). Yani __all__bize kullandığınızda Geçerli isim yüklenir ve ithal edilecek tüm modüllerini belirtir from package import *.

En büyük farkı zaman yani, ihmal ilanını __all__bir paket en içinde __init__.py, deyim from package import *(istisnalar belgelerinde açıklandığı birlikte, yukarıdaki bağlantıya bakın) hiç bir şey ithal olmayacaktır.

Eğer ihmal varsa Öte yandan, __all__bir modülde, "rol aldı ithal" modülünde tanımlanan tüm adlar (bir alt çizgi ile başlayan değil) ithal edecek.

Cevap 16/05/2013 saat 20:01
kaynak kullanıcı

oy
97

Python __all__ açıklar?

Ben değişken görmeye devam __all__farklı yılında seti __init__.pydosyaları.

Bu ne işe yarar?

Ne geliyor __all__do?

Bu bir modülden semantik "kamu" isimleri beyan eder. Bir isim varsa __all__, kullanıcıların kullanmak beklenir ve onlar değişmeyeceği beklentisi olabilir.

Aynı zamanda programlı etkiler sahip olacaktır:

import *

__all__Bir modülde, mesela module.py:

__all__ = ['foo', 'Bar']

Ne zaman demektir import *modülünden, sadece o isimler __all__ithal edilmektedir:

from module import *               # imports foo and Bar

Belgeler araçları

Belgeler ve kod otomatik tamamlama araçları (aslında, olmalı) da inceleyebilirler __all__bir modülden olarak temin göstermek için hangi isimler belirlemek.

__init__.py Bir dizini bir Python paketi yapar

Gönderen docs :

__init__.pyDosyaları Python paketlerini içeren dizinler olarak algılaması için gereklidir; Bu istemeden sonradan modül arama yolunda geçerli modülleri gizleme gelen böyle dize olarak ortak bir adla dizinleri önlemek için yapılır.

En basit durumda, __init__.pysadece boş bir dosya olabilir, ancak paketi ilk kod yürütmesine veya ayarlayabilirsiniz __all__değişkeni.

Yani __init__.pyilan edebilir __all__bir için paketin .

bir API Yönetme:

Bir paket içerisinde birbirlerini ithal edebilir modülden oluşur, ama bu mutlaka bir ile birbirine bağlanmış __init__.pydosyası. Bu dosya dizini gerçek bir Python paketi kılan budur. Örneğin, aşağıdakilere sahip ki:

 package/
   |-__init__.py # makes directory a Python package
   |-module_1.py
   |-module_2.py

içinde __init__.pyyazdığınız:

from module_1 import *
from module_2 import *

ve module_1size vardır:

__all__ = ['foo',]

ve module_2size vardır:

__all__ = ['Bar',]

Ve şimdi bu kadar gibi, paket alırken başkasının kullanabileceği tam bir api sundular:

import package
package.foo()
package.Bar()

Ve onlar doldurmasını Modüllerinizi oluştururken kullandığınız tüm diğer adlara sahip olmayacaktır packagead.

__all__ içinde __init__.py

daha çalışmadan sonra, belki modüller çok büyük ve bölmek gerektiğini karar verdik. Yani aşağıdakileri yapın:

 package/
   |-__init__.py
   |-module_1/
   |  |-__init__.py
   |  |-foo_implementation.py
   |-module_2/
      |-__init__.py
      |-Bar_implementation.py

Ve her __init__.pybir beyan __all__, örneğin module_1:

from foo_implementation import *
__all__ = ['foo']

Ve module_2 en __init__.py:

from Bar_implementation import *
__all__ = ['Bar']

Ve kolayca yerine alt paketin en modül düzeyi Alt paket düzeyinde yönetebileceğiniz API şeyler ekleyebilir. Eğer API yeni bir isim eklemek istiyorsanız, sadece güncellemek __init__.pymodule_2 içinde, örneğin:

from Bar_implementation import *
from Baz_implementation import *
__all__ = ['Bar', 'Baz']

Yayınlamaya hazır olmazsak da Bazüst düzey API, üst düzeyde __init__.pysahip olabilir:

from module_1 import *       # also constrained by __all__'s
from module_2 import *       # in the __init__.py's
__all__ = ['foo', 'Bar']     # further constraining the names advertised

Kullanıcıların varlığından haberdar olup olmadığını ve Bazonlar bunu kullanabilirsiniz:

import package
package.Baz()

bu konuda bilmiyorum ama eğer (gibi diğer araçları pydoc ) kendilerine haber olmaz.

Daha sonra zaman bunu değiştirebilir Bazprime time için hazır:

from module_1 import *
from module_2 import *
__all__ = ['foo', 'Bar', 'Baz']

Prefixing _karşı __all__:

Varsayılan olarak, Python bir ile başlamayın bütün isimleri ihraç edecek _. Kesinlikle olabilir Bu mekanizma güveniyor. Python standart kütüphanesinde Bazı paketler, aslında, do bu itimat, ancak, bunlar örneğin, onların ithalatı için diğer ad bunu ctypes/__init__.py:

import os as _os, sys as _sys

Kullanılması _tekrar isimleri adlandırma fazlalık kaldırır çünkü kongre daha şık olabilir. Ama (eğer onlardan bir sürü var ise) o ithalat yük eklenir ve öyle kolay sadece ve istediğiniz son şey süresiz sadece bir uygulama detay olması amaçlanmıştır şeyi taşıması için sahip olmaktır - sürekli bunu unutmak bir önek unuttuğu için _bir işlev adlandırırken.

Ben şahsen bir yazma __all__kodumu kullanabilir diğerleri kullandıkları ve kullanmamalıdır bilmek böylece modülleri için benim geliştirme yaşam döngüsü içinde erken.

Standart kütüphanede çoğu paketleri de kullanabilirsiniz __all__.

Ne zaman kaçınarak __all__mantıklı

Bu sopa mantıklı _yerine önek kongre __all__:

  • Erken gelişim modunda hala ve hiçbir kullanıcımız var ve sürekli API verdiği edilmektedir.
  • Belki kullanıcıya sahip, ancak ne API kapsayacak unittests varsa ve hala aktif olarak API ekleyerek ve geliştirme ayarlama yapıyor.

bir exportdekoratör

Kullanmanın dezavantajı __all__iki kez fonksiyonları ve sınıfları ihraç edilen isimleri yazmak zorunda olmasıdır - ve bilgi tanımları ayrı bir yerde saklanır. Biz olabilir bu sorunu çözmek için bir dekoratör kullanın.

Ben ambalaj üzerinde David Beazley konuşmasından böyle bir ihracat dekoratör için bir fikrim var. Bu uygulama CPython geleneksel ithalatçısı iyi çalışıyor gibi görünüyor. Özel bir ithalat kanca veya sisteminiz varsa, bunu garanti etmiyoruz, ancak bunu kabul etmeleri halinde, vazgeçme oldukça önemsiz - sadece elle geri adlar eklemek gerekir__all__

Yani, örneğin, bir yardımcı kütüphane, sen dekoratör tanımlarsınız:

import sys

def export(fn):
    mod = sys.modules[fn.__module__]
    if hasattr(mod, '__all__'):
        mod.__all__.append(fn.__name__)
    else:
        mod.__all__ = [fn.__name__]
    return fn

Bir tanımlarsınız nerede ve ardından __all__, bunu yapmak:

$ cat > main.py
from lib import export
__all__ = [] # optional - we create a list if __all__ is not there.

@export
def foo(): pass

@export
def bar():
    'bar'

def main():
    print('main')

if __name__ == '__main__':
    main()

Ve bu ana olarak çalıştırmak veya başka bir işlev tarafından ithal edip çalışıyor.

$ cat > run.py
import main
main.main()

$ python run.py
main

Ve API provizyon import *çok çalışacaktır:

$ cat > run.py
from main import *
foo()
bar()
main() # expected to error here, not exported

$ python run.py
Traceback (most recent call last):
  File "run.py", line 4, in <module>
    main() # expected to error here, not exported
NameError: name 'main' is not defined
Cevap 29/02/2016 saat 21:58
kaynak kullanıcı

oy
83

Ayrıca pydoc gösterecektir neyi değiştirir:

module1.py

a = "A"
b = "B"
c = "C"

module2.py

__all__ = ['a', 'b']

a = "A"
b = "B"
c = "C"

$ Pydoc module1

Modül module1 Yardımı:

ADI
    module1

DOSYA
    module1.py

VERİ 
    bir = 'A'
     B = 'B'
     C = 'C'

$ Pydoc modül2

Modül Module2 Yardımı:

ADI
    modül2

DOSYA
    module2.py

VERİ 
    __all__ = [ 'a', 'b']
     bir = 'A'
     B = 'B'

Ben beyan __all__şeyleri canlı tercüman oturumlarında önce hiç kullanmadıysanız kullanırken de iç detaylar çizgi olarak, bunlar gerçekten yardımcı, bütün modüllerde.

Cevap 15/05/2010 saat 04:22
kaynak kullanıcı

oy
48

Gönderen (An Resmi olmayan) Python Referans Wiki :

Bir modül ile tanımlanan kamu isimler adında bir değişken için modülün ad kontrol ederek belirlenir __all__; tanımlanmışsa, bu da bu modül tarafından tanımlanmıştır ya da içe isimler şeritlerinin bir dizi olmalıdır. Verilen isimler __all__tüm kamu olarak kabul edilir ve var olmaya ihtiyaç vardır. Eğer __all__tanımlı değil, kamu isimleri kümesi bir alt çizgi karakteri ( "_") ile başlamayan modülün ad alanında bulunan tüm adlarını içerir. __all__tüm kamu API içermelidir. (Örneğin ithal ve modülü içinde kullanıldı kütüphane modül olarak) API parçası olmayan yanlışlıkla ihracat öğeleri önlemek amaçlanmaktadır.

Cevap 04/09/2008 saat 22:31
kaynak kullanıcı

oy
17

__all__özelleştirir yıldız işareti içindefrom <module> import *

__all__özelleştirir yıldız işareti içindefrom <package> import *


Bir modül bir olduğunu .pyithal edilecek anlamına dosyası.

Bir paket bir bir dizindir __init__.pydosyası. Bir paketi genellikle modülleri içerir.

""" cheese.py """

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__sağlayan insanlar a "kamu" özelliklerini bilmek modülü . [ @AaronHall ] Ayrıca, pydoc onları tanır. [ @Longpoke ]

dan modül import *

Bkz nasıl swissve cheddaryerel ad haline getirilir, ancak gouda:

>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined

Olmadan __all__, herhangi bir sembol (yani bir alt çizgi ile başlamaz) mevcuttur olurdu.


Olmadan İthalat *etkilenmez__all__


ithalat modülü

>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)

dan modül ithalat adlarıyla

>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)

ithalat modülü olarak localName

>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)

In __init__.pya dosyaya paketinde __all__ kamu modülleri veya diğer nesnelerin adları ile dizeleri listesidir. Bu özellikler joker ithalatı için kullanılabilir. Modüllerin olduğu gibi, __all__özelleştirir *paketinden joker-aktarırken. [ @MartinStettner ]

İşte bir alıntı var Python MySQL Connector __init__.py :

__all__ = [
    'MySQLConnection', 'Connect', 'custom_error_exception',

    # Some useful constants
    'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
    'HAVE_CEXT',

    # Error handling
    'Error', 'Warning',

    ...etc...

    ]

Onlar okuyucuları ve birçok otomatik araçlar [karıştırmayın] olarak Joker ithalat ... kaçınılmalıdır.

[ PEP 8 , @ToolmakerSteve]

Cevap 20/03/2016 saat 20:20
kaynak kullanıcı

oy
7

__all__Python modülünün genel API belgelemek için kullanılır. İsteğe bağlı olmakla birlikte, __all__kullanılmalıdır.

İşte alakalı alıntıdır Python dili referans :

Bir modül ile tanımlanan kamu isimler adında bir değişken için modülün ad kontrol ederek belirlenir __all__; tanımlanmışsa, bu da bu modül tarafından tanımlanmıştır ya da içe isimler şeritlerinin bir dizi olmalıdır. Verilen isimler __all__tüm kamu olarak kabul edilir ve var olmaya ihtiyaç vardır. Eğer __all__tanımlı değil, kamu isimleri kümesi bir alt çizgi karakteri ( '_') ile başlamayan modülün ad alanında bulunan tüm adlarını içerir. __all__tüm kamu API içermelidir. (Örneğin ithal ve modülü içinde kullanıldı kütüphane modül olarak) API parçası olmayan yanlışlıkla ihracat öğeleri önlemek amaçlanmaktadır.

PEP 8 o da zaman ithal isimleri ortak API parçası olmayan açıklık getiriyor rağmen, benzer ifadeler kullanır __all__yoktur:

Daha iyi destek içgözlem için, modüller açıkça kullanarak kamu API isimleri ilan etmeli __all__niteliğini. Ayar __all__boş listeye modül hiçbir kamu API olduğunu gösterir.

[...]

İthal isimleri daima bir uygulama ayrıntı düşünülmelidir. Onlar açıkça belgelenmiş gibi içeren modülün API parçası, olmadıkça Diğer modüller ithal isimlerle dolaylı erişime bağlı kalmamalıdırlar os.pathveya paketin __init__alt modüllerinin gelen işlevselliği sunar modülü.

Diğer yanıtlar işaret Dahası, __all__etkinleştirmek için kullanılır paketleri içe joker :

Ithalat beyanı aşağıdaki kuralını kullanır: Bir paketin eğer __init__.pykod adlı bir liste tanımlar __all__, ne zaman ithal edilmesi modül isimlerinin listesi olarak alınır from package import *karşılaşılır.

Cevap 26/04/2016 saat 01:39
kaynak kullanıcı

oy
1

Varolan cevaplara ek olarak, __all__bir liste olması gerekmez. Belgelere uyarınca importaçıklamada , tanımlanan eğer __all__bir olmalıdır dizeleri dizisi modülü tarafından tanımlanmış veya ithal isimlerdir. Yani siz de bir başlığın kullanabilir kaydetmek bazı bellek ve CPU döngülerini. Sadece modül tek kamu ad tanımlayan durumunda bir virgül unutma:

__all__ = ('some_name',)

Cevap 09/01/2019 saat 14:48
kaynak kullanıcı

oy
1

Kısa cevap

__all__etkiler from <module> import *ifadeleri.

Uzun cevap

Bu örneği ele alalım:

foo
├── bar.py
└── __init__.py

In foo/__init__.py:

  • Biz define yoksa (Örtülü) __all__, daha sonra from foo import *sadece ithalat isimleri tanımlanan olacaktır foo/__init__.py.

  • Biz tanımlarsanız (Explicit) __all__ = [], daha sonra from foo import *hiçbir şey ithal edecek.

  • Biz tanımlarsanız (Explicit) __all__ = [ <name1>, ... ], daha sonra from foo import *sadece bu isimleri ithal edecek.

Örtük durumda piton ile başlayan isimler içe unutmayın _. Ancak, kullanarak bu tür isimleri ithal zorlayabilir __all__.

Sen Python dokümanı görüntüleyebilir burada .

Cevap 03/04/2018 saat 01:19
kaynak kullanıcı

oy
0

Bu açıkça PEP8 tanımlanır burada :

Genel Değişken Adları

(Şimdi bu değişkenler sadece bir modül içerisindeki kullanım içindir umalım.) Konvansiyonlar fonksiyonlar için aynıdır hakkındadır.

Aracılığıyla kullanılmak üzere tasarlanmıştır modüller from M import *kullanmalıdır __all__ihraç globalsi önlemek için mekanizmayı, ya da (bu globaller "modül kamuya açık olmayan" dır belirtmek için yapmak isteyebilirsiniz) bir alt çizgi ile bu tür globalsi prefixing eski kuralını kullanın.

PEP8 ana Python dağılımı standart kütüphane içeren Python kodu için kodlama kuralları içerir. Daha sen bu izleyin kökenli daha yakındır.

Cevap 17/06/2019 saat 20:55
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more