Soru “İthalat” neden bu şekilde uygulandı?


>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> math.pi
3
>>> import math
>>> math.pi
3

İlk soru: Neden alamıyorum math.pi geri? 

düşündüm import tüm tanımlanmış değişkenleri ve fonksiyonları mevcut kapsamı içine alır. Ve şimdiki kapsamda bir değişken adı zaten varsa, o zaman yerini alacaktı.

Evet, bunu değiştirir:

>>> pi = 3
>>> from math import *
>>> pi
3.141592653589793

Sonra belki düşündüm math.pi = 3 atama aslında mülkü math class(yoksa öyle mi math module?), hangisi import math ithal.

Haklıydım:

>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> from math import *
>>> pi
3

Yani, öyle görünüyor:
Yaparsan import xsonra ithal eder x sınıf gibi bir şey olarak. Ve eğer x.property'de değişiklik yaparsanız, değişiklik modülde kalsın, böylece tekrar her içe aktardığınızda değiştirilmiş bir versiyon olur. 

Gerçek soru:

  1. Neden ki import bu şekilde mi uygulandı? Neden izin vermeyelim import math yeni, değiştirilmemiş bir kopyasını içe aktar math? Neden içe aktarılsın? math değişime açık?
  2. Almak için herhangi bir geçici çözüm var mı math.pi yaptıktan sonra geri math.pi = 3 (dışında math.pi = 3.141592653589793, tabii ki)?
  3. Aslında düşündüm ki import math üzerinde tercih edilir from math import *. Ama bu davranış bana, eğer bu şekilde yaparsam başka birisinin içe aktarılmış modülümü değiştirdiğinden endişelenmemi engelliyor ... Nasıl yapmalıyım import?

18
2017-09-18 03:46


Menşei


Nick Coghlan’ın Unwary için Tuzaklar iyi (ilgili) bir okuma. - kojiro
@kojiro Bağlantı için teşekkürler! - octref


Cevaplar:


Bir modül birçok kez içe aktarılabilir. bir import deyim sadece referansı yükler sys.modules. Eğer import deyim de modülü disketten yeniden yükledi, oldukça yavaş olurdu. Bu gibi bir modülü değiştirmek çok sıra dışıdır ve yalnızca nadir, belgelenmiş koşullar altında yapılır, dolayısıyla endişelenmenize gerek yoktur.

Nasıl Tekrar yükle bir modül:

>>> import imp
>>> imp.reload(math)
<module 'math' (built-in)>
>>> math.pi
3.141592653589793

10
2017-09-18 03:50



imp.reload = lambda x: "Woops" - scohe001
@Josh reload(imp) - DanielB
lütfen insanlara modülleri yeniden yüklemelerini söyleme. gerçekten hiç ihtiyacın yok - jterrace
@jterrace: ipython'daki koşular arasında değişen bir modülü ayıklarken ne yapıyorsunuz? - Neil G
@octref: reload () gerçekten komutları verirken bir modülün kaynak kodunu değiştirirken yalnızca etkileşimli kabukta kullanılmalıdır. Çalışan bir programsa, gerçekten reload () kullanmamalısınız. Bunun yerine, rahatsız edici modülü bulup kaldırmanız veya onun maymun düzeltme davranışını kontrol etmenin bir yolunu bulmanız gerekir. Reload () ile ilgili sorun, tümüyle farklı, uyumsuz olarak çalışan aynı değişkenlerin / sınıfların / yöntemlerin çoklu kopyaları ile sonuçlanabilmenizdir ve bu, her türlü kabusa yol açacaktır. - Lie Ryan


Python sadece herhangi bir modülün bir kopyasını oluşturur. Bir modülü içe aktarmak, orijinali tekrar tekrar kullanır. Bunun nedeni, A ve B modüllerinin E ve F, vb. İthal edilen C ve D'yi alması, C ve D'nin iki kez yüklenmesini ve E ve F'nin 4 kez yüklenmesini vb. grafikler, bellek bitmeden önce yedekli modülleri yüklemek için birkaç dakika harcayacaksınız. Ayrıca, A ve B içe aktarılan A, A'yı içe aktarırsa, yinelemeli bir döngüde sıkışırsınız ve yine de, yararlı bir şey yapmadan bellekten çıkmış olursunuz.

Çözüm: Diğer modüllerin içeriğiyle vidalama. Eğer yaparsan, bu tercüman geneli bir değişiklik. Bunu yapmak isteyeceğiniz durumlar vardır, bu yüzden Python size izin verir, ama genellikle kötü bir fikirdir.


13
2017-09-18 03:56



Ahh, nasıl çalıştığını görüyorum. from math import * Modüle bir modül bırakmaz, böylece modülü değiştiremiyorum ... teşekkürler! - octref
Endişenizi anlamıyorum, yorumlarınızdan ve sorularınızdan dolayı, bunu yaptığınızı düşündüğünüz anlaşılıyor. import diğer kodlayıcıların kullanması için. - justhalf
Bu benim merakımdan şu soruyu soruyorum ... Ve, OOP dillerindeki tüm erişim düzenleyicileri neydi? - octref
Python için, OOP sadece Kongre tarafından. Python'da, bazı cevapların vurgulandığı gibi Java'da olduğu gibi gerçek erişim değiştiricileri yoktur. Aldığınız herhangi bir modülün her üyesine erişebilirsiniz. Sözleşme, diğer modülden erişilmemesi gereken değişkenlerin bir alt çizgi ile hazırlanmalıdır. Yani, adında bir değişken görürseniz _vocabulary Bir modülde, bu, orijinal yazarın insanların doğrudan bu değişkene erişmesini istemediği anlamına gelir, ancak Python bunu yapmaya devam etmenizi sağlar. - justhalf
@justhalf: Java'da aslında bytecode seviyesinde uygulanan erişim düzenleyici değildir; Java ile bile, yansıma özel üyelerle sohbet etmek için kullanılabilir. - Lie Ryan


İçe aktarma davranışı, modüllerin duruma sahip olmasını sağlamaya yöneliktir. Örneğin, başlatma kodunu çalıştıran bir modül, init zamanında ne olduğuna bağlı olarak her türlü farklı davranışa sahip olabilir (iyi bir örnek, işletim sisteminizin hangi işletim sistemine bağlı olduğuna bağlı olarak yol alt modülünün farklı sürümlerini şeffaf olarak yükleyen os modülüdür). . Her zamanki davranış, başlatma işlemini tekrar tekrar başlatmadan çok sayıda farklı kodun modüle erişmesine izin vermek için vardır. Dahası, modüller diğer dillerdeki benzer statik sınıfları işlerler - durumu koruyabilirler ve genellikle global değişkenlere alternatif olarak kullanılırlar: örn. Yerel kültür değişkenlerini (para birimi formatı, vb.) Ayarlamak için yerel ayar modülünü kullanabilirsiniz. locale.setlocale kodunuzun bir kısmında ve local.getlocale Bir diğerinde ise küresel bir değişken oluşturmanın güzel bir alternatifi.

Örneğiniz, elbette, zayıflığa işaret ediyor. Klasik python prensiplerinden biri

Hepimiz burada yetişkiniz.

Dil, yazarın bir modülün veya dersin içeriğini kilitlemesine izin veren Java veya C # içinde bulabileceğiniz gizlilik yönetimi özelliklerinin çoğunu sağlamaz. Kötü niyetli (ya da sadece intihara eğilimli) bir şey hissediyorsanız, örneğinizde yaptığınız gibi bir şey yapın: pi'yi 3'e eşitleyin ya da bir işlevi bir değişkene ya da her türlü diğer kötü şeylere dönüştürün. Dil, bunu zorlaştırmak için tasarlanmamıştır - sorumlu olmak kodlayıcılara kalmış.

@Josh Lee'nin cevabı, bir diski temelli duruma getirecek bir modülü yenilemenin doğru yolu olan yeniden yüklemenin nasıl kullanılacağını gösterir. Yeniden yükleme bilgeliği, çoğunlukla modülde başlangıç ​​kodunun ne olduğuna ve ayrıca söz konusu modül tarafından içe aktarılan veya içe aktarılan diğer modüllerin ağına bağlıdır.


6
2017-09-18 04:02



Peki bu, Java üzerinden Python'u sevmemin nedenlerinden biri. Belki de Java'nın erişim düzenleyicilerinin hedefi, aynı proje üzerinde çalışan takımda daha fazla yer alır (böylece takım arkadaşlarınızı API'nizi takip etmeye zorlarsınız, uygulamanızla uğraşmak zorunda kalmazsınız ...) - octref
kesinlikle - tüm erişim şey, onların ihtiyaçlarını kullanarak insanların hiç tanımadığı veya hatta duymadığı dev projelerin veya şirketlerin bağırsaklarında çalışan insanlar için tasarlanmıştır. - theodox