2012-11-15 27 views
6

__init__() yönteminde bir içe aktarımım olması gerekir (çünkü bu içe aktarımı yalnızca örnekleme yaparken çalıştırmam gerekir).Python içe aktarma __init __()

Ancak __init__() dışında içe aktarma işlemini göremiyorum, kapsam __init__ ile sınırlı midir? nasıl yapılır?

+6

İçe aktarılan içeriğe bağlıdır ... Bunu yapmak istemediğinizi hissediyorum, ancak kullanım durumunuz nedir? –

+0

Neden başka türlerde de ihtiyacınız varsa, sadece __init __() 'ye aktarmak istiyorsunuz? –

+1

Çünkü bağımlılığı olan bir sınıfım var ve bağımlılığı yalnızca bir kişi bu sınıfı kullanıyorsa yüklensin (bir örnek oluşturur) – tapioco123

cevap

8

İçe aktarılan adlar geçerli kapsamlara bağlı olduğundan, bir işlev içindeki içe aktarma yalnızca yerel bir adaya bağlanır. Kesinlikle ardından küresel DAİREMİZ olması gerekiyor __init__ şey ithal etmek varsa

, ilk global olarak ithal ismi işaretlemek:

>>> def foo(): 
...  global sys 
...  import sys 
... 
>>> sys 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'sys' is not defined 
>>> foo() 
>>> sys 
<module 'sys' (built-in)> 

ancak bu genellikle garip ve bulmak olağanüstü zor hatalar yol açar . Bunu yapmayın, sadece ithalatlarınızı modül kapsamında yapın.

class Foo(object): 
    def __init__(self): 
     import os 
     self.join = os.path.join 

ama yine o kullanılacak en iyi uygulama değil: diğer sınıf yöntemleri içinde ithal adını gerekiyorsa

, ayrıca bir örnek değişkeni ithal ismi atayabilir.

+0

O zaman ne önerirsiniz? Soyut bir sınıf (abc) ve abc sınıfını uygulayan sınıfları olan bir sınıfım var. Ve bir dizgeye dayanan bir işlev, bu abc sınıfını uygulayacak bir sınıfı arar ve ardından işlevini çağırır (özet tarafından istenir). Bu işlevler, sqlite ve diğer xml ayrıştırıcısına ihtiyaç duyduğu gibi tamamen farklı şeyler gerektirebilir. –

+0

Belki bu uygulamaları kendi modüllerine yerleştirebilir misiniz? Ama gerçekten, bu ithalatı en üst seviyeye çıkarmakla ilgili sorun nedir? –

+0

Kendi modülünün bir sorumluluğu yoktur, çünkü dir() çok gizlidir ve birçok şeyi doğrulamak (ve kodu kırmak için). Üst seviyedeki bir soru da söz konusu değildir, çünkü bazı sınıflar sqlite, tizter, minidom vb. Gibi büyük modüllere gereksinim duyarlar ve bunları modüllerin içe aktarımıyla ithal etmek istemeyiz. gerektirir. –

4

İhtiyacınız olan başka yerlere tekrar içe aktarabilirsiniz - ilk kez önbelleğe alınacak ve bu nedenle nispeten ucuz olur.

Alternatif olarak, geçerli genel ad alanlarını globals()['name'] = local_imported_module_name gibi bir şeyle değiştirebilirsiniz.

DÜZENLEME: Kayıt için, kesinlikle çalışacaktır globals() işlevini kullanarak her ne kadar, bir "temizleyici" çözüm global ve sonra import bunu, diğer bazı cevaplar söylediğim gibi modülün ismini ilan etmek olacağını düşünüyorum.

+2

'tekrar içe aktar 'doğru çözümdür. Bu ücretsizdir, çünkü modül ithalatları sys.modules'de global olarak önbelleğe alınır. – katrielalex

+1

@katrielalex: "Önbelleğe alınacak" bölümü kastediyorum. – martineau

+0

Kabul - Ben sadece vurgulayarak =) – katrielalex

2

Eğer ithalat sonucu sınıfın diğer nesnelere görünür olmasını istiyorsanız, örneğin bir sınıf veya örnek değişkeni

için ithalat kaynaklanan nesne atamak gerekir:

>>> class Foo(object): 
... def __init__(self): 
...  import math 
...  self.bar = math.pi 
... def zoo(self): 
...  return self.bar 
... 
>>> a = Foo() 
>>> a.zoo() 
3.141592653589793 
+0

Bu iyi bir fikir, ama sanırım OP daha çok 'Foo.math =' veya 'self.math = math' - yani tüm modül gibi bir şey istiyor. – martineau

3

import ifadesi, içe aktarılan adları yalnızca geçerli kapsamda kullanılabilir kılar. __init__ içinde bulunan bir import foo, yalnızca __init__ yönteminde görülebilen bir foo oluşturur.

import foo modülüne erişmesi gereken herhangi bir yönteme ya da kendiniz bir kez daha içe aktarmayı yazarken bulduysanız, modül kapsamına almak için global anahtar sözcüğünü kullanabilirsiniz.

class Wayne(object): 
    def __init__(self): 
     global foo 
     import foo 
İlgili konular