Soru Python sınıflarında “özel” değişkenler var mı?


Java dünyasından geliyorum ve Bruce Eckels'i okuyorum. Python 3 Desenler, Yemek Tarifleri ve Deyimler.

Dersleri okurken, Python'da örnek değişkenleri bildirmeye gerek olmadığını söylemeye devam eder. Onları sadece yapıcıda kullanıyorsun, ve bomlar, oradalar.

Yani örneğin:

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

Eğer bu doğruysa, o zaman sınıfın herhangi bir nesnesi Simple sadece değişkenin değerini değiştirebilir s sınıfın dışında.

Örneğin:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

Java'da, kamu / özel / korunan değişkenler hakkında bilgi verilmiştir. Bu anahtar kelimeler anlamlıdır çünkü zaman zaman, sınıfın dışındaki hiç kimsenin erişimi olmayan bir sınıftaki değişkenleri istediğiniz gibi kullanırsınız.

Bu neden Python'da gerekli değil?


409
2017-10-29 01:54


Menşei


Demek istedin örnek değişkenler değil sınıf değişkenler, değil mi? - PaulMcG
Özellikleri kontrol etmelisiniz: docs.python.org/library/functions.html#property. Sadece alıcıyı kullanın ve değişkeniniz korunacaktır. - rubik
neden kullanıyorsun self1btw? - njzk2
Tekrar, neden kullanıyorsun self1? - noɥʇʎԀʎzɐɹƆ
@SumukhBarve yazı özeldir. Ne kadar ironik. - noɥʇʎԀʎzɐɹƆ


Cevaplar:


Kültürel. Python'da, diğer sınıfların örnek veya sınıf değişkenlerine yazmazsınız. Java'da hiçbir şey aynı şeyi yapmanıza engel olmaz. Gerçekten mi Her şeyden önce, aynı etkiyi elde etmek için sınıfın kaynağını her zaman düzenleyebilirsiniz. Python bu güvenlik duygusunu düşürüyor ve programcıları sorumlu olmaya teşvik ediyor. Pratikte, bu çok güzel çalışıyor.

Herhangi bir nedenle özel değişkenleri taklit etmek isterseniz, her zaman __ önek PEP 8. Python gibi değişkenlerin isimlerini mangles __foo böylece onları içeren sınıfın dışındaki kodlara kolayca görülemezler. kutu yeteri kadar kararlıysan kutu Çalışırsanız Java'nın korumaları hakkında bilgi edinin).

Aynı sözleşmeyle _ önek anlamı teknik olarak engellenmemiş olsanız bile uzak durun. Başka bir sınıfın değişkenlerine benzemeyen __foo veya _bar.


757
2017-10-29 02:01



Bu mantıklı. Ancak, java'da sınıf dışındaki özel değişkenlere erişmek için herhangi bir yol olduğunu düşünmüyorum (aslında ders sınıfının kaynağını değiştirmek hariç). Var mı? - Omnipresent
Ben python yolunu tercih etme eğilimindeyim, ama java yolunun siz çıktıkça anlamsız olduğunu düşünmüyorum. Özel bir şeyi hızlı bir şekilde bildirmek, kodu okuyan birinin çok yararlı bir şey olduğunu söyler: Bu alan yalnızca bu sınıf içinde değiştirilir. - Ned
@Omnipresent, yansımayı kullanarak yapabilirsiniz. - rapadura
@dVaffection "Evet, bir Jedi'nin gücü kuvvetten akar. Fakat karanlık tarafa dikkat edin. Öfke, korku, saldırganlık, kuvvetin karanlık tarafı onlardır. Kolayca akarlar, kavgada size katılmaya çabuklar. karanlık yoldan başlayıp, sonsuza kadar kaderinize hükmedecek, Obi-Wan'ın çırağı yaptığı gibi, onu tüketeceksiniz. " - m93a
Bunu doğru bir şekilde söyleyeyim, bu yüzden Python kamu ve özel nitelikleri uygulamıyor çünkü “bu bir güvenlik iddiası ve programcıların sorumlu olmasını teşvik ediyor”, ancak toplum özel değişkenleri ve yöntemleri göstermek için “_” kullanımını teşvik ediyor? Belki python kesinlikle kamu ve özel hayır olmalı? Temel amaçları, bir sınıfla etkileşimde bulunmak için hangi API'yi kullanmanız gerektiğini size söylemektir. Bu yöntemleri kullanmanız ve bunları kullanmamanızı isteyen bir belge olarak hizmet ederler. Onlar bir "güvenlik iddiası" değiller, IDE tarafından size rehberlik etmek için bile kullanılabilen API belgeleridir! - PedroD


Python'daki özel değişkenler az ya da çok kesindir: yorumlayıcı kasıtlı olarak değişkeni yeniden adlandırır.

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

Şimdi, erişmeye çalışırsanız __var sınıf tanımının dışında, başarısız olur:

 >>>x = A()
 >>>x.__var # this will return error: "A has no attribute __var"

 >>>x.printVar() # this gives back 123

Ama bununla kolayca uzaklaşabilirsiniz:

 >>>x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

 >>>x._A__var = 456 # you now know the masked name of private variables
 >>>x.printVar() # this gives back 456

Muhtemelen OOP'taki yöntemlerin şu şekilde çağrıldığını biliyorsunuzdur: x.printVar() => A.printVar(x), Eğer A.printVar() bazı alanlara erişebilir x, bu alana da erişilebilir dışında  A.printVar()... her şeyden önce, yeniden kullanılabilirlik için fonksiyonlar yaratılır, içindeki ifadelere özel bir güç yoktur.

Bir derleyici söz konusu olduğunda oyun farklıdır (gizlilik bir derleyici seviyesi kavramdır). Erişim denetimi değiştiricileri ile sınıf tanımını bilir, böylece kurallar derleme zamanında izlenmezse hata verebilir


101
2017-09-26 22:06



Kısacası, bu kapsülleme değildir - watashiSHUN
PHP'nin goofy özel değişkenleri ile benzer bir şey olup olmadığını merak ediyorum - özel değişkenler yorumlanmış dilde gerçekten anlam ifade etmiyorlar - yani x değişkeninin ne olduğunu bilmeliyse, optimizasyon ne yapabilir? - NoBugs
Özel değişkenlerin modelini nasıl rasgele hale getirebiliriz? - crisron
@crisron aynı soru - IanS
kullanma self.__dic__ = {} kullanımını reddetti __str__ yöntem. Kullanılacak herhangi bir iş var mı __str__ bu içerikte? - arsho


Yukarıdaki yorumların çoğunda belirtildiği gibi, Erişim Düzenleyicilerinin ana amacını unutmayalım: Kod kullanıcılarına neyin değişmesi gerektiğini ve neyin yapılmaması gerektiğini anlamasına yardımcı olmak. Özel bir alan gördüğünüzde bununla uğraşmazsınız. Bu yüzden çoğunlukla Python'da _ ve __ ile kolayca elde edilen sözdizimsel şekerdir.


18
2017-11-17 05:17



Sanırım bu kadar önemli bir nokta. Kod hata ayıklama yaparken (Ben hatalar tanıtmak için zayıf bir yapıyorum), hangi sınıfların üye değişkeni değiştirebileceğini bilmek hata ayıklama işlemini basitleştirir. En azından, değişken bazı kapsamlara göre korunuyorsa. Benzer bir kavram C ++ 'da const işlevidir. ben bilmek oradaki üye değişkenleri değişmedi ve bu yüzden bu yönteme kötü bir değişken ayarının potansiyel sebebi olarak bakmıyorum. Sınıf genişletme / ekleme özelliklerinin daha sonraki gelişimini yapabilmesine rağmen, kodun görünürlüğünü sınırlamak, hata ayıklamayı kolaylaştırır. - MrMas


"Java'da, kamu / özel / korunan değişkenler hakkında öğretildik"

"Neden python'da gerekli değil?"

Aynı sebepten dolayı değil gereklidir Java'da.

Kullanmakta özgürsünüz - ya da kullanmıyorsunuz private ve protected.

Bir Python ve Java programcısı olarak şunu buldum private ve protected çok, çok önemli tasarım kavramları. Ama pratik bir konu olarak, on binlerce Java ve Python satırında, asla aslında Kullanılmış private veya protected.

Neden olmasın?

İşte sorum "kimden korunuyorsun?"

Ekibimdeki diğer programcılar mı? Kaynağı var. Korunabilecekleri zaman ne anlama gelir?

Diğer takımlardaki diğer programcılar mı? Aynı şirket için çalışıyorlar. Onlar - bir telefon görüşmesi ile - kaynağı olsun.

Müşteriler? Bu işe-işe programlama (genellikle). Müşteriler (genellikle) kendi koduna sahipler.

Yani, kim - tam olarak - onu koruyor muyum?

Sağ. API yorum bloklarını okumayı reddeden şizofrenik sosyopat.


13
2017-10-29 02:28



-1: Porculus'a katılıyorum. Bu, erişimi yasaklamak ya da bir şeyi saklamakla ilgili değil. üstü kapalı API belgeleri. Geliştiriciler yanı sıra derleyiciler / tercüman / kod denetleyicisi hangi üyelerin kullanılmasını önerdiğini ve hangilerinin dokunulmaması gerektiğini (veya en azından dikkatle) kolayca görebilirler. Çoğu durumda, bir sınıfın veya modülün tüm üyeleri halka açıksa korkunç bir karmaşa olurdu. Özel / korunan / kamu üyelerinin bir hizmet olarak ayrıldığını düşünün: “Hey, bu üyeler içte ve muhtemelen sizin için yararlı olmasa da önemlidir.” - Oben Sonne
@ S. Lott: API belgelerinin daha yüksek önceliğe sahip olduğunu ve çoğu zaman bir API'nin kullanım amaçlarıyla iletişim kurmanın tek yolu olduğunu kabul ediyorum. Ancak bazen üye isimleri ve görünürlükleri (özel / kamu açısından) kendi başlarına yeterli derecede konuşurlar. Ayrıca, örtülü dökümantasyon fikrinin, API incelemesi olmaksızın editörlerde iyi çalışmadığını, ancak IDE'lerde kodun tamamlanmasına gerçekten yardımcı olduğunu görüyorum. Daha önce bir süre önce API belgelerini okuduğunuzu varsayarsak, bir sınıfı nasıl kullanacağınızı hatırlamanıza yardımcı olur. Özel ve kamu üyeleri arasında ayrım yapılmazsa işler akıllı olmazdı. - Oben Sonne
Tartışmanın sonuna kadar, Porculus ve Oben’in burada talep ettiği her şey, “alt çizgi ile bir ön ek” konvansiyonu (ve bu sözleşmenin derleyici uygulamasının neden olabileceği zarar olmadan) tarafından yeterince uygun bir şekilde ele alınır. - ncoghlan
@hiwaylon: Kesinlikle doğru. Tamamen katılıyorum. Kapsülleme bir tasarım özelliğidir. Gizlilik, kapsüllenen bir tasarım yapılmasına yardımcı olmaz. Üyelerin, yapmamaları gereken özellikleri kullanmasını önlemek için yalnızca derleyici desteği sağlar. Arayüze programlamak, tanımlanmış bir arayüze sahip olmak ve onu belgelemek meselesidir. Private, belgeleri okuyamayan veya takip etmeyi reddeden kişilere yardımcı olmak için sadece derleyici desteği. - S.Lott
@ S.Lott Ben bir python adamı değilim, bu yüzden o bakış açısıyla yorum yapmayacağım. Ancak bir java geliştiricisi olarak bu gerçekten dehşet verici bir tavsiyedir. -1 - dbyrne


Python, sınıf ismini otomatik olarak iki altçizgi ile başlayan herhangi bir tanımlayıcıya önceden ekleyen bir özellik aracılığıyla, özel tanımlayıcılar için sınırlı bir desteğe sahiptir. Bu programcıya şeffaftır, çoğunlukla, ancak net etki bu şekilde adlandırılan değişkenlerin özel değişkenler olarak kullanılabileceğidir.

Görmek İşte daha fazlası için.

Genel olarak, Python'un nesne yönelimi uygulaması diğer dillere kıyasla biraz ilkeldir. Ama aslında bundan zevk alıyorum. Bu çok kavramsal olarak basit bir uygulama ve dilin dinamik stili ile iyi uyuyor.


8
2017-10-29 01:59





Alt çizgi kongresinde özel değişkenlerin varyasyonu vardır.

In [5]: class test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:     

In [6]: x = test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'test' object has no attribute '__private_method'

Bazı ince farklılıklar vardır, ancak programlama deseni ideolojik saflık için, yeterince iyi.

Konseptleri daha yakından uygulayan @yeni dekoratörler var, ancak YMMV. Muhtemelen bir kişi meta kullanan bir sınıf tanımını da yazabilirdi.


8
2017-09-02 01:19



Bunun partiye oldukça geç olduğunu biliyorum. Ancak bu bağlantı, sorun gidermek için google'da görünür. Bu hikayenin tamamını anlatmıyor. __x sınıf içinde bir değişken olarak A aslında derleyici tarafından yeniden yazılmıştır _A__xhala tamamen özel değil ve hala erişilebilir. - Zorf
Tabii ki, adında bir değişken görürsem _A__x, Ona dokunmayacağım. Bulaşıcı olabilir. Cehennemden uzaklaşacağım. - Mateen Ulhaq
Mateen doğru fikre sahip. _A__x "burada ejderhalar" olarak yorumlanabilir - Shayne


Özel değişkenleri kullandığım tek zaman, değişkene yazarken ya da okurken başka şeyler yapmam gerektiğidir ve bu yüzden bir setter ve / veya getter kullanımını zorlamak zorundayım.

Yine bu daha önce de belirtildiği gibi, kültüre gider. Diğer sınıf değişkenlerinin okunması ve yazılmasının herkes için ücretsiz olduğu projeler üzerinde çalışıyorum. Bir uygulama kullanımdan kaldırıldığında, bu işlevi kullanan tüm kod yollarını tanımlamak çok daha uzun sürdü. Belirleyiciler ve alıcılar kullanılmaya zorlandığında, kullanımdan kaldırılan yöntemin çağrıldığını ve onu çağıran kod yolunun tanımlanması için bir hata ayıklama ifadesi kolayca yazılabilir.

Herkesin bir uzantı yazabileceği bir projede bulunduğunuzda, birkaç sürümde ortadan kaybolacak olan kullanımdan kaldırılmış yöntemler hakkında kullanıcıları bilgilendirmek, dolayısıyla yükseltmeler sonrasında modülün bozulmasını minimumda tutmak için hayati önem taşır.

Yani benim cevabım; Siz ve meslektaşlarınız basit bir kod setini koruyorsanız, sınıf değişkenlerini korumak her zaman gerekli değildir. Genişletilebilir bir sistem yazıyorsanız, kod kullanılarak tüm uzantıların yakalanması gereken çekirdeğe yapılan değişikliklerin yapılması zorunlu hale gelir.


7
2018-04-28 17:22





özel ve korunan kavramlar çok önemlidir. Ancak python - geliştirme için mevcut kısıtlı kaynaklarla prototip oluşturma ve hızlı geliştirme için sadece bir araçtır, bu yüzden koruma seviyelerinin bir kısmı python'da bu kadar sıkı olmamalıdır. Sınıftaki "__" yi kullanabilir, düzgün çalışır, ancak yeterince iyi görünmez - bu alandaki her erişim bu karakterleri içerir.

Ayrıca, python OOP konseptinin, mükemmel OOP konseptine çok daha yakın, smaltalk veya yakut olmadığını fark edebilirsiniz. Hatta C # veya Java daha yakın.

Python çok iyi bir araçtır. Ama OOP dili basitleştirilmiştir. Sözdizimsel ve kavramsal olarak basitleştirildi. Python varlığının temel amacı, geliştiricilere, yüksek düzeyde soyutlama düzeyi ile kolay okunabilir kod yazmayı çok hızlı bir şekilde yapma olanağı sağlamaktır.


6
2017-07-17 06:00



Özel ve Korumalı arkadaki önemli olan, statik olarak derlenmiş dillerdeki derleyicinin özel yönteme yönelik diirect çağrıları oluşturabilmesi, ancak kamu yöntemleri için bir arama tablosuna dayanması gerektiğidir. Thiis sadece dinamik dillerle ilgili bir sorun değil. Son olarak C ++ gibi diller, kalıtım ve yöntem çözümü için imalar vardır. Python ve Ruby, OO'nun çok benzer uygulamalarına sahiptir, dolayısıyla karşılaştırma anlamsızdır. Smalltalk aslında kamu / özel mesajlara dair bir fikri yoktur. Bir kategori olarak özel eklemek için ücretsiz, ancak tamamen danışmanlık. - Shayne
Benim iddiamı daha ileriye. Kozayan bir hijyen bakış açısına göre Frorm, evet kapsülleme için önemlidir, ama değil gerekli Bunun için, @özel (vb) dekoratörler her şeyden daha isteklidirler, fakat özel / kamu, statik olmayan bir dilde optimizasyon için yararlı hiçbir şey eklemediğinden, onun gibi derlenmiş bir dilde olduğu gibi derin bir düzeyde uygulanmaz. java veya c - Shayne


Daha önce de belirtildiği gibi, bir değişken veya yöntemin bir alt çizgi ile ön ekleyerek özel olduğunu belirtebilirsiniz. Eğer böyle hissetmiyorsanız, her zaman property dekoratör. İşte bir örnek:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

Bu şekilde, referans veren bir kişi veya bir şey bar aslında geri dönüşün değerine referans veriyor bar Değişkenin kendisinden ziyade fonksiyona sahiptir ve bu yüzden erişilebilir ancak değiştirilemez. Ancak, birileri gerçekten istediyse, sadece kullanabilirlerdi _bar ve buna yeni bir değer atayın. Tekrar tekrar söylendiği gibi, birinin gizlemek istediğiniz değişkenlere ve yöntemlere erişmesini önlemek için kesin bir yol yoktur. Ancak, kullanarak property Bir değişkenin düzenlenmemesi için gönderebileceğiniz en net mesajdır. property Ayrıca burada açıklandığı gibi daha karmaşık alıcı / ayarlayıcı / deleter erişim yolları için de kullanılabilir: https://docs.python.org/3/library/functions.html#property


5
2018-04-14 04:19





Konuya "diriltme" için özür dilerim ama umarım bu birilerine yardımcı olur:

Python3'te, Java'daki gibi sınıf özniteliklerini "kapsüllemek" istiyorsanız, bununla aynı şeyi yapabilirsiniz:

class Simple:
    def __init__(self, str):
        print("inside the simple constructor")
        self.__s = str

    def show(self):
        print(self.__s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

Bunu yapmak için şunu yapın:

ss = Simple("lol")
ss.show()

Bunu not et: print(ss.__s) bir hata atar.

Pratikte, Python3 global özellik ismini gizleyecektir. Bunu, Java'daki gibi "özel" bir özellik gibi çevirmek. Özniteliğin adı hala global, ancak başka dillerde özel bir özellik gibi erişilemez bir şekilde.

Ama korkma. Fark etmez. Bu da işi yapıyor. ;)


3
2017-08-15 01:30



Bu Python 1.5.2 IIRC'den beri mevcuttu ve yine de öznitelikli ismiyle erişime erişimi engellemiyor. - bruno desthuilliers