Yazdıklarınıza göre, kritik bir anlayış parçasını kaçırıyorsunuz: sınıf ve nesne arasındaki fark. __init__
bir sınıfı başlatmaz, bir sınıfın veya nesnenin bir örneğini başlatır. Her köpeğin rengi vardır, ancak köpeklerin sınıf olarak yoktur. Her köpeğin dört veya daha az ayağı vardır, ancak köpek sınıfında yoktur. Sınıf, bir nesnenin konseptidir. Fido ve Spot'u gördüğünüzde, benzerliklerini, köpekliklerini anlarsınız. Sınıf bu.
Dediğinde
class Dog:
def __init__(self, legs, colour):
self.legs = legs
self.colour = colour
fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")
Diyorsun ki, Fido 4 bacaklı kahverengi bir köpek, Spot biraz sakat ve çoğunlukla sarı. __init__
İşlevi, bir yapıcısı denir, ya da başlatıcı ve bir sınıfın yeni bir örneğini oluşturduğunuzda otomatik olarak adlandırılır. Bu işlev içinde, yeni oluşturulan nesne parametreye atanır self
. Gösterim self.legs
, legs
değişkendeki nesnenin adı verilen bir özniteliktir self
. Öznitelikler bir çeşit değişken gibidir, ancak bir nesnenin durumunu veya nesnenin kullanabileceği belirli eylemleri (işlevleri) tanımlar.
Ancak, colour
köpekliğin kendisi için belirlemediğinizi unutmayın - bu soyut bir kavramdır. Sınıflar üzerinde anlamlı olan nitelikler vardır. Örneğin, population_size
böyle bir şey - Fido'yu saymak mantıklı değil çünkü Fido her zaman birdir. Köpekleri saymak mantıklı. Diyelim ki dünyada 200 milyon köpek var. Bu, Dog sınıfının malıdır. Fido'nun 200 milyon sayısıyla ilgisi yok, Spot da yok. Bu colour
veya legs
üstü "örnek özniteliklerinin" aksine "sınıf özniteliği" olarak adlandırılır .
Şimdi, daha az köpek ve daha programlama ile ilgili bir şeye. Aşağıda yazdığım gibi, bir şeyler eklemek için sınıf mantıklı değil - bu sınıf nedir? Python'daki sınıflar, benzer şekilde davranan farklı veri koleksiyonlarından oluşur. Köpekler sınıfı, Fido ve Spot ve bunlara benzer 199999999998 diğer hayvanlardan oluşur ve hepsi de elektrik direklerine işer. Bir şeyler eklemek için sınıf nelerden oluşur? İçlerinde bulunan hangi verilere göre farklılık gösterirler? Ve hangi eylemleri paylaşıyorlar?
Ancak sayılar ... bunlar daha ilginç konular. Tamsayılar diyelim. Köpeklerden çok daha fazlası var. Python'un zaten tam sayılara sahip olduğunu biliyorum, ama hadi aptalı oynayalım ve onları tekrar "uygulayalım" (hile yaparak ve Python'un tam sayılarını kullanarak).
Yani, Tamsayılar bir sınıftır. Bazı verileri (değeri) ve bazı davranışları ("beni bu sayıya ekle") vardır. Şunu gösterelim:
class MyInteger:
def __init__(self, newvalue)
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
def add(self, other):
# when an integer wants to add itself to another integer,
# we'll take their values and add them together,
# then make a new integer with the result value.
return MyInteger(self.value + other.value)
three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8
Bu biraz kırılgan ( other
bir MyInteger olacağını varsayıyoruz), ancak şimdi görmezden geleceğiz. Gerçek kodda yapmayız; emin olmak için test ederdik ve hatta belki de zorlarız ("sen bir tamsayı değil misin? Aman tanrım, bir olmak için 10 nanosaniye var! 9 ... 8 ....")
Kesirleri bile tanımlayabiliriz. Kesirler ayrıca kendilerini nasıl toplayacaklarını da bilirler.
class MyFraction:
def __init__(self, newnumerator, newdenominator)
self.numerator = newnumerator
self.denominator = newdenominator
# because every fraction is described by these two things
def add(self, other):
newdenominator = self.denominator * other.denominator
newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
return MyFraction(newnumerator, newdenominator)
Tamsayılardan bile daha fazla kesir vardır (gerçekten değil, ancak bilgisayarlar bunu bilmiyor). İki yapalım:
half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6
Aslında burada hiçbir şey beyan etmiyorsunuz. Nitelikler yeni bir değişken türü gibidir. Normal değişkenlerin yalnızca bir değeri vardır. Yazın diyelim colour = "grey"
. Sen adında başka değişkeni olamaz colour
olduğu "fuchsia"
değil kodda aynı yerde -.
Diziler bunu bir dereceye kadar çözer. Derseniz colour = ["grey", "fuchsia"]
, değişkene içine iki renk yığılmış var, ancak (bu durumda, 0 veya 1) konumlarına göre ayırt.
Nitelikler, bir nesneye bağlı değişkenlerdir. Dizilerde olduğu gibi , farklı köpeklerde birçok colour
değişkenimiz olabilir . Öyleyse, bir değişken, ama başka. İlki, değişken içindeki nesneye bağlıdır ; ikinci ,. Şimdi, veya aradığınızda , her zaman görünmez bir parametre olacak ve bu parametre listesinin önündeki sarkan fazladan bir parametreye atanacaktır. Geleneksel olarak adlandırılır ve noktanın önündeki nesnenin değerini alır. Böylece, Köpeğin (kurucu) içinde, yeni Köpeğin ortaya çıkacağı şey olacaktır; içinde 's , değişkendeki nesneye bağlanacaktır . Böylece,fido.colour
spot.colour
fido
spot
Dog(4, "brown")
three.add(five)
self
__init__
self
MyInteger
add
self
three
three.value
dışında aynı değişken olacak add
şekilde, self.value
içinde add
.
Söylersem the_mangy_one = fido
, ben olarak bilinen nesneye atıfta başlayacak fido
bir başka isimle. Şu andan itibaren fido.colour
, tamamen aynı değişkendir the_mangy_one.colour
.
Yani, içindeki şeyler __init__
. Bunları, Köpeğin doğum belgesine bir şeyler yazıyormuş gibi düşünebilirsiniz. colour
kendi başına rastgele bir değişkendir, herhangi bir şey içerebilir. fido.colour
veya self.colour
Köpeğin kimlik sayfasındaki bir form alanı gibidir; ve __init__
katip ilk kez dolduruyor.
Daha net mi?
DÜZENLEME : Aşağıdaki yorumun genişletilmesi:
Nesnelerin bir listesini kastediyorsun , değil mi?
Her şeyden önce, fido
aslında bir nesne değil. Şu anda bir nesneyi içeren bir değişkendir, tıpkı sizin dediğinizde olduğu gibi x = 5
, x
şu anda beş sayısını içeren bir değişkendir. Daha sonra fikrinizi değiştirirseniz, bunu yapabilirsiniz fido = Cat(4, "pleasing")
(bir sınıf oluşturduğunuz sürece Cat
) ve fido
o andan itibaren bir kedi nesnesi "içerebilirsiniz". Bunu yaparsanız fido = x
, o zaman beş numara içerecek ve hiçbir hayvan nesnesi olmayacak.
Bir sınıf, siz onları takip etmek için özel olarak kod yazmadığınız sürece örneklerini kendi başına bilmez. Örneğin:
class Cat:
census = [] #define census array
def __init__(self, legs, colour):
self.colour = colour
self.legs = legs
Cat.census.append(self)
Burada, census
sınıfın sınıf düzeyinde bir özelliği var Cat
.
fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that
Almayacağınızı unutmayın [fluffy, sparky]
. Bunlar sadece değişken isimlerdir. Kedilerin kendi adlarının olmasını istiyorsanız, ad için ayrı bir öznitelik oluşturmanız ve ardından __str__
bu adı döndürmek için yöntemi geçersiz kılmanız gerekir . Bu yöntemin (yani sınıfa bağlı işlevi, tıpkı add
veya gibi __init__
) amacı, nesneyi yazdırırken olduğu gibi bir dizeye nasıl dönüştürebileceğini açıklamaktır.