Python Değişken Bildirimi


87

Python öğrenmek ve bazı temel şüpheleri vardır.

1. Değişken bildirimini (burada yol) olarak gördüm

class writer:
    path = ""

bazen, açık bir bildirim yoktur, ancak baştan başlar __init__.

def __init__(self, name):
    self.name = name

Amacını anlıyorum __init__, ancak diğer işlevlerde değişken bildirmek tavsiye edilir mi?

2. Özel bir türü tutmak için nasıl değişken oluşturabilirim?

class writer:
    path = "" # string value
    customObj = ??

12
Ve 2. soru ile ilgili olarak: Python'da değişkenlerin type: değerleri yoktur. Böylece herhangi bir değişken, özel nesnelerinizi tutabilir.
jpaugh

4
İsimleri / tanımlayıcıları değişkenler olarak düşünmeyi bırakırsanız yardımcı olacaktır . Bunlar referanslar nesnelere
John La Rooy

2
@gnibbler Ya da onlara isimler ...
detly

1
@detly, isimlerin kötü bir seçim olduğunu düşünüyorum. Nesnelerin genellikle tek bir adı varken, bir nesnenin birden çok referansı olabilir
John La Rooy

2
@JohnClements, ancak python matematik gibi çalışmıyor. Python'u anlamak istiyorsanız, __name__özniteliğe sahip nesnelerin bir "adı" olduğunu bilmeniz gerekir . Tüm nesnelerin bir __name__niteliği yoktur, ancak yine de bunlara referanslarınız olabilir. Bir "referans" a "isim" demeye başlarsak, yeni başlayanlara yolun aşağısında bir kötü hizmet yapıyoruz.
John La Rooy

Yanıtlar:


205

Tamam, ilk önce ilk şeyler.

Python'da "değişken bildirimi" veya "değişken başlatma" diye bir şey yoktur.

Basitçe "atama" dediğimiz şey var, ancak muhtemelen "adlandırma" olarak adlandırılmalıdır.

Atama, "sol taraftaki bu ad, daha önce (varsa) ne atıfta bulunduğuna bakılmaksızın artık sağ tarafın değerlendirilmesinin sonucunu ifade etmektedir" anlamına gelir.

foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

Bu nedenle, Python adlarının (muhtemelen "değişkenlerden" daha iyi bir terim) ilişkili türleri yoktur; değerler yapar. Aynı adı, türüne bakılmaksızın herhangi bir şeye yeniden uygulayabilirsiniz, ancak nesnenin yine de türüne bağlı bir davranışı vardır. İsim, değere (nesneye) başvurmanın bir yoludur. Bu ikinci soruya cevap verir: Sen do not Özel bir türü tutmak için değişkenler oluşturun. Belirli bir türü tutmak için değişkenler oluşturmazsınız. Değişkenler "yaratmıyorsunuz". Nesnelere isim veriyorsunuz.

İkinci nokta: Python, sınıflar söz konusu olduğunda çok basit bir kuralı izler, bu aslında Java, C ++ ve C # gibi dillerin yaptıklarından çok daha tutarlıdır: bloğun içinde bildirilen her şey classsınıfın bir parçasıdır . Dolayısıyla, defburada yazılan işlevler ( ) yöntemlerdir, yani sınıf nesnesinin bir parçasıdır (örnek başına depolanmaz), tıpkı Java, C ++ ve C # 'da olduğu gibi; ancak buradaki diğer isimler de sınıfın bir parçasıdır. Yine, isimler sadece isimlerdir ve ilişkili türleri yoktur ve Python'da işlevler de nesnelerdir . Böylece:

class Example:
    data = 42
    def method(self): pass

Python'da sınıflar da nesnelerdir .

Şimdi , s olan her şeyin sınıfını temsil eden isimli bir nesne yarattık . Bu nesnenin kullanıcı tarafından sağlanan iki özniteliği vardır (C ++ 'da, "üyeler"; C #' da "alanlar veya özellikler veya yöntemler"; Java'da "alanlar veya yöntemler"). Bunlardan biri adlandırılır ve tamsayı değerini saklar . Diğeri adlandırılır ve bir işlev nesnesi depolar. (Python'un otomatik olarak eklediği birkaç özellik daha vardır.)ExampleExampledata42method

Bu nitelikler yine de nesnenin gerçekten bir parçası değildir. Temelde, bir nesne, artık bölünemeyen şeylere gelene kadar, daha fazla addan (öznitelik adları) oluşan bir demettir. Bu nedenle, kasıtlı olarak ayarladıysanız, değerler bir sınıfın farklı örnekleri arasında veya hatta farklı sınıflardan nesneler arasında paylaşılabilir.

Bir örnek oluşturalım:

x = Example()

Şimdi x, adında ayrı bir nesnemiz var ve bu nesnenin bir örneği Example. dataVe methodnesnenin aslında bir parçası, ama biz yine de aracılığıyla onları bakabilirsiniz xçünkü Python perde arkasında yaptığı bazı büyü. methodÖzellikle yukarı baktığımızda, bunun yerine bir "bağlı yöntem" elde edeceğiz (onu çağırdığımızda x, selfparametre olarak otomatik olarak geçer , bu, Example.methoddoğrudan bakarsak gerçekleşemez ).

Kullanmaya çalıştığımızda ne olur x.data?

İncelediğimizde, önce nesneye bakılır. Nesnede bulunamazsa, Python sınıfa bakar.

Ancak, atadığımız zaman x.data, Python nesne üzerinde bir nitelik oluşturacaktır. Bu olacak değil sınıf özelliğini değiştirin.

Bu, nesne başlatma yapmamızı sağlar . Python __init__, mevcutsa, yeni örnekler oluşturulduklarında sınıfın yöntemini otomatik olarak çağırır . Bu yöntemde, her nesnede o özniteliğin başlangıç ​​değerlerini ayarlamak için öznitelikleri atayabiliriz:

class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

Şimdi, bir nameoluşturduğumuzda a belirtmeliyiz Exampleve her örneğin kendine ait bir örneği vardır name. Python , bir örneğe Example.namebaktığımızda sınıf özniteliğini yoksayar .name, çünkü ilk önce örneğin özniteliği bulunur.

Son bir uyarı: değişiklik (mutasyon) ve atama farklı şeylerdir!

Python'da dizeler değişmezdir. Değiştirilemezler. Ne zaman yaparsan:

a = 'hi '
b = a
a += 'mom'

Sen değişmez orijinal 'merhaba' dizesini. Python'da bu imkansızdır. Bunun yerine, yeni bir dize oluşturursunuz 'hi mom've bunun yerine bir isim olmayı abırakıp onun yerine 'hi 'bir isim olmaya başlarsınız 'hi mom'. Biz yapılan bbir isim 'hi 'de ve yeniden uygulandıktan sonra aadını, bhala bir isimdir 'hi 'çünkü 'hi 'hala var ve değiştirilmemiştir.

Ancak listeler değiştirilebilir:

a = [1, 2, 3]
b = a
a += [4]

Şimdi b[1, 2, 3, 4] de, çünkü badı geçen şey için bir isim yaptık ave sonra o şeyi değiştirdik. Adlandırılacak yeni bir liste oluşturmadık açünkü Python +=, listeler için farklı davranır .

Bu, nesneler için önemlidir çünkü sınıf özniteliği olarak bir listeniz varsa ve listeyi değiştirmek için bir örnek kullandıysanız, değişiklik diğer tüm örneklerde "görülür". Bunun nedeni, (a) verilerin aslında sınıf nesnesinin bir parçası olması ve herhangi bir örnek nesnesi olmamasıdır; (b) Listeyi değiştirdiğiniz ve basit bir atama yapmadığınız için, sınıf niteliğini gizleyen yeni bir örnek niteliği oluşturmadınız.


12
Bu yüzden onlara 'tanımlayıcılar' diyoruz . :-)
Martijn Pieters

@Karl_Knechtel sondaki string örneğinizde, eğer onu asla 'b' olarak adlandırmazsak 'hi'ye ne olur? Bu bir hafıza sızıntısı mı?
heretoinfinity

2
@heretoinfinity: hayır; Python, ulaşılamayan nesneleri serbest bırakmak için çöp toplamayı kullanıyor
John Clements

Değişken beyanı bu videoda iyice açıklanmıştır: youtube.com/watch?v=ao2N37E-D9s .
Ishaq Khan

cevap için bu videoyu izleyin youtube.com/…
Thao N

23

Bu 6 yıl geç olabilir, ancak Python 3.5 ve üzeri sürümlerde şöyle bir değişken türü bildirirsiniz:

variable_name: type_name

veya bu:

variable_name # type: shinyType

Yani sizin durumunuzda ( CustomObjecttanımlanmış bir sınıfınız varsa) şunları yapabilirsiniz:

customObj: CustomObject

Bkz bu ya o daha fazla bilgi için.


Bu geleneksel anlamda bir bildirim değil, yine de statik tip denetleyicilerinin ve IDE'lerin işaret edebileceği, ancak yine de çalışıp başarısız olacağı bir ipucu.
PhilHibbs

@PhilHibbs Yine de başarısız olmuyor. "Başarısız" derken neyi kastediyorsun?
O. Aroesti

Demek istediğim, eğer yaparsan a: intve sonra yaparsan a='hello, world!'başarısız olmayacak, bu yüzden bu bir int olarak ilan edilmiyor ve sadece bir int. "Başarısız olmayacak" demeliydim, benim hatam. Eğer olsaydı a: int, a='hello, world!', a=a+1o statik yazdığınız dilde derleme başarısız gerekir.
PhilHibbs

22

Python'da yeni değişkenler bildirmeye gerek yoktur. İşlevlerdeki veya modüllerdeki değişkenlerden bahsediyorsak, bildirim gerekmez. Sadece ihtiyacınız bir isim bir değer atamak: mymagic = "Magic". Python'daki değişkenler her türden değeri tutabilir ve bunu kısıtlayamazsınız.

Sorunuz özellikle sınıflar, nesneler ve örnek değişkenleri hakkında sorular soruyor. Örnek değişkenler oluşturmak için deyimsel yolu olduğunu __init__başka hiçbir yerde yöntemi ve - Eğer süre olabilir başka yöntemlerde yeni örnek değişkenler oluşturabilir, hatta ilgisiz kodunda, sadece kötü bir fikirdir. Kodunuzun akıl yürütmesini veya sürdürülmesini zorlaştırır.

Yani mesela:

class Thing(object):

    def __init__(self, magic):
        self.magic = magic

Kolay. Şimdi bu sınıfın örneklerinin bir magicözelliği var:

thingo = Thing("More magic")
# thingo.magic is now "More magic"

Sınıfın ad alanında değişkenler yaratmak, tamamen farklı davranışlara yol açar. İşlevsel olarak farklıdır ve bunu yalnızca belirli bir nedeniniz varsa yapmalısınız. Örneğin:

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

Şimdi dene:

thingo = Thing()
Thing.magic = 1
# thingo.magic is now 1

Veya:

class Thing(object):

    magic = ["More", "magic"]

    def __init__(self):
        pass

thing1 = Thing()
thing2 = Thing()
thing1.magic.append("here")
# thing1.magic AND thing2.magic is now ["More", "magic", "here"]

Bunun nedeni, sınıfın kendi ad alanının, ondan oluşturulan nesnelerin ad alanından farklı olmasıdır. Bunu biraz daha araştırmanızı size bırakacağım.

Ana mesaj, deyimsel Python'un (a) __init__yönteminizdeki nesne özniteliklerini başlatması ve (b) sınıfınızın davranışını gerektiği gibi belgelemesidir. Şimdiye kadar yazdığınız her şey için tam gelişmiş Sfenks düzeyinde belgeleme zahmetine girmenize gerek yok, ancak en azından sizin veya bir başkasının alması gereken ayrıntılar hakkında bazı yorumlar.



1

Değişkenlerin kapsamı vardır, bu nedenle evet, işlevinize özgü değişkenlere sahip olmak uygundur. Her zaman tanımları konusunda açık olmanız gerekmez; genellikle sadece kullanabilirsiniz. Yalnızca değişkenin türüne özel bir şey yapmak istiyorsanız, örneğin bir listeye eklemek gibi, kullanmaya başlamadan önce onları tanımlamanız gerekir. Bunun tipik bir örneği.

list = []
for i in stuff:
  list.append(i)

Bu arada, bu listeyi kurmanın pek de iyi bir yolu değil. Şunu söylemek daha iyi olur:

list = [i for i in stuff] # list comprehension

... ama ben dalıyorum.

Diğer sorunuz. Özel nesnenin kendisi bir sınıf olmalıdır.

class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.