http___programarcadegames.com_index.php_chapter_introduction_to_classes_lang_tr_1.xml
1.1 1.2 2.1 3.1 4.1 5.1 5.2 6.1 7.1 7.2 8.1 9.1 10.1 11.1 12.1 13.1 14.1 14.2 15.1 16.1 16.2 17.1 18.1 19.1 20.1 21.1 22.1 23.1 25.1 26.1 27.1 27.2 28.1 29.1 30.1 31.1 31.2 32.1 33.1 34.1 35.1 36.1 37.1 38.1 39.1 40.1 41.1 41.2 42.1 43.1 44.1 45.1 46.1 46.2 47.1 48.1 48.2 49.1 52.1 52.2 53.1 53.2 54.1 55.1 56.1 57.1 58.1 59.1 60.1 60.2 61.1 62.1 63.1 64.1 65.1 66.1 67.1 68.1 69.1 70.1 71.1 72.1 73.1 74.1 75.1 76.1 77.1 78.1 79.1 80.1 81.1 82.1 83.1 84.1 85.1 86.1 87.1 87.2 88.1 88.2 88.3 89.1 90.1 91.1 92.1 93.1 94.1 95.1 96.1 97.1 98.1 99.1 100.1 101.1 102.1 103.1 104.1 105.1 106.1 107.1 108.1 109.1 110.1 111.1 112.1 113.1 114.1 115.1 115.2 116.1 117.1 118.1 119.1 120.1 121.1 122.1 123.1 124.1 125.1 126.1 127.1 128.1 129.1 130.1 131.1 132.1 133.1 134.1 136.1 137.1 138.1 139.1 140.1 141.1 142.1 143.1 144.1 145.1 146.1 147.1 148.1 149.1 150.1 151.1 152.1 153.1 154.1 155.1 156.1 157.1 158.1 159.1 160.1 161.1 162.1 162.2 163.1 164.1 165.1 166.1 167.1 168.1 168.2 169.1 170.1 171.1 173.1 174.1 175.1 176.1 177.1 178.1 179.1 180.1 181.1 182.1 183.1 184.1 185.1 186.1 187.1 188.1 189.1 190.1 191.1 192.1 193.1 194.1 195.1 196.1 197.1 198.1 199.1 200.1 201.1 202.1 203.1 204.1 205.1 206.1 207.1 208.1 209.1 210.1 211.1 211.2 212.1 213.1 214.1 215.1 216.1 217.1 218.1 219.1 220.1 222.1 223.1 224.1 225.1 226.1 227.1 228.1 229.1 230.1 231.1 231.2 232.1 233.1 234.1 235.1 236.1 237.1 241.1 242.1 243.1 244.1 245.1 246.1 247.1 248.1 249.1 250.1 251.1 252.1 253.1 254.1 255.1 256.1 257.1 258.1 259.1 260.1 260.2 261.1 261.2 262.1 263.1 263.2 263.3 264.1 265.1 266.1 267.1 268.1 269.1 270.1 271.1 271.2 271.3 272.1 273.1 274.1 275.1 276.1 277.1 277.2 278.1 279.1 280.1 281.1 282.1 283.1 284.1 285.1 286.1 287.1 288.1 288.2 289.1 290.1 291.1 291.2
When you create a Python application there is one thing that can make your life a lot easier: class inheritance. Let’s learn how to use it. Class Inheritance allows to create classes based on other classes with the aim of reusing Python code that has already been implemented instead of having to reimplement similar code. The first two concepts to learn about Python inheritance are the Parent class and Child class. What is a Parent class? A Parent class is a class you inherit from in your program to reuse its code. It’s also called Base class or Superclass. What is a Child class? The Child class is the class that inherits from the Parent class. It’s also called Derived class or Subclass. We will work on a simple football game and show how inheritance works in Python. But first let’s start with some super important inheritance basics! Table of Contents Difference Between a Parent and a Child Class We have talked about Parent and Child classes… What’s the difference between these two when it comes to the way we define them? Let’s start by defining a class called A in the way we define any class in Python. To simplify this example we will just use the pass statement in the implementation of each class. What is the pass statement in a Python class? The pass statement is used in Python classes to define a class without implementing any code in it (e.g. attributes and methods). Using the pass statement is a common technique to create the structure of your program and avoid errors raised by the interpreter due to missing implementation in a class. I’m using the pass statement because I don’t want you to focus on the code of the classes right now but just on the concept of inheritance itself. class A: pass Class A is just a normal class. What error do we see if we don’t include the pass statement in our class? $ python inheritance.py File "inheritance.py", line 2 SyntaxError: unexpected EOF while parsing The Python interpreter doesn’t like code that only contains the first line of the class A definition without pass. So, going back to our working example. What makes class A a Parent class? The fact that in our program we create a class called B that inherits (or derives) from it: class B(A): pass Notice that after the name of the class B I have also included class A within parentheses. This means that B inherits from A. In other words B is a child class and A is its parent class. But this doesn’t end here… We can define a class called C that inherits from B: class C(B): pass You can see that the role of a class when it comes to inheritance is not set in stone…what do I mean? A class can be both a parent and child class like we have seen with class B in our example. This is very powerful and it allows you to create complex Python programs with very few lines of code. And now, let’s have a look at a practical example of inheritance. A First Example of Class Inheritance in Python Firstly, we create a base class called Player. Its constructor takes a name and a sport: class Player: def __init__(self, name, sport): self.name = name self.sport = sport We could use the Player class as Parent class from which we can derive classes for players in different sports. Let’s create child classes that represent football players. I will define four child classes for the four football roles: goalkeeper, defender, midfielder and striker. As we have seen before, here is how to create a class in Python that inherits from another class. We use the class statement and additionally we specify the name of the class we want to inherit from after the name of our class within parentheses: class ChildClass(ParentClass): Even if we don’t define any methods in our child class we can still call the methods from the parent class as if they were implemented in the child one. This is the power of inheritance. We will define our child classes is such a way that the sport attribute is automatically set. Here is an example for the Goalkeeper class: class Goalkeeper(Player): def __init__(self, name): super().__init__(name, 'football') As you can see, the parent class Player is between parentheses. Then we define the __init__ method (the constructor) that replaces the __init__ method inherited from the parent class. If the __init__ method is not defined in a child class then the __init__ method from the parent class is automatically used. In the constructor we use the method super() that refers to the parent class. We use it to call the constructor of the parent class and we pass to it: - The name of the player provided when an object of type Goalkeeper is created. - The ‘football’ sport. The same applies for all the roles: class Player: def __init__(self, name, sport): self.name = name self.sport = sport class Goalkeeper(Player): def __init__(self, name): super().__init__(name, 'football') class Defender(Player): def __init__(self, name): super().__init__(name, 'football') class Midfielder(Player): def __init__(self, name): super().__init__(name, 'football') class Striker(Player): def __init__(self, name): super().__init__(name, 'football') Now, let’s create an object of type striker: striker1 = Striker('James Striker') print(striker1.__dict__) As you can see, the namespace of the new object contains the attributes name and role: {'name': 'James Striker', 'sport': 'football'} The next step will be to add a new attribute to our classes. Adding an Attribute to a Child Class It’s time to add an attribute to our child classes. An attribute that only applies to football players and not necessarily to all sport players. This is the power of inheritance. We can inherit functionality from a parent class and then provide additional functionalities that are only specific to child classes. It allows to avoid repeating code that is already in the parent class. One attribute that is specific to football players but doesn’t apply to all players is the role. For example, add the role to our Striker class: class Striker(Player): def __init__(self, name): super().__init__(name, 'football') self.role = 'striker' We can now see the role attribute in the namespace of the instance of child class: >>> striker1 = Striker('James Striker') >>> print(striker1.__dict__) {'name': 'James Striker', 'sport': 'football', 'role': 'striker'} This code works but it’s not generic… What if we want to create object of type Goalkeeper, Defender or Midfielder? To make it generic we have to add the new attribute to the constructor of each child class. So, for example, the Striker class becomes: class Striker(Player): def __init__(self, name, role): super().__init__(name, 'football') self.role = role We need to remember to include the role when we create our striker object, otherwise we will receive the following error: $ python football.py Traceback (most recent call last): File "football.py", line 28, in striker1 = Striker('James Striker') TypeError: __init__() missing 1 required positional argument: 'role' So, here is how we create the striker object now: striker1 = Striker('James Striker', 'striker') Quite cool! Our classes are slowly getting better. Adding a Method to the Parent Class And now… …let’s add a method called play to our parent class: class Player: def __init__(self, name, sport): self.name = name self.sport = sport def play(self): pass The method I have defined only includes the pass statement that, as we have seen before, in Python does nothing. So, why are we adding it to the method? Let’s create an object of type Player and the run the play method: player1 = Player('Player1', 'football') player1.play() You will see that when you run this code you won’t get any output from the play method. Let’s try to remove the pass statement from the method and see what happens when we execute the same code above: $ python football.py File "football.py", line 9 class Goalkeeper(Player): IndentationError: expected an indented block This time Python raises an indentation error caused by missing code inside the play method (that immediately precedes the definition of the class Goalkeeper. So, we will add a print message to the play method of the parent class and move to the implementation of the same method for some of the child classes. Here is how all our classes look like so far: class Player: def __init__(self, name, sport): self.name = name self.sport = sport def play(self): print("Player {} starts running".format(self.name)) class Goalkeeper(Player): def __init__(self, name, role): super().__init__(name, 'football') self.role = role class Defender(Player): def __init__(self, name, role): super().__init__(name, 'football') self.role = role class Midfielder(Player): def __init__(self, name, role): super().__init__(name, 'football') self.role = role class Striker(Player): def __init__(self, name, role): super().__init__(name, 'football') self.role = role Now, we can see how the play method is inherited by a child class. Let’s create an object of type Midfielder and execute the play method on it: midfielder1 = Midfielder('James Midfielder', 'midfielder') midfielder1.play() The output is: $ python football.py Player James Midfielder starts running When we invoke the play method on the Midfielder object the play method of the Player class is invoked. This is due to the Method Resolution Order. The Method Resolution Order (MRO) is the order in which Python looks for a method within a hierarchy of classes. You can use the mro() method of a class to see the resolution order: print(Midfielder.mro()) The output shows that the order used by Python to resolve methods in this case is: - Midfielder class. - Player class. - object class that is the class most classes in Python inherit from. So, in our scenario Python doesn’t find the play method in the Midfielder class and uses the same method from the parent class Player. Override a Method in a Python Class Overriding a method means defining a method in the child class with the same name of one of the methods in the parent class. In this case, we can define the play method in the Midfielder class as follows: class Midfielder(Player): def __init__(self, name, role): super().__init__(name, 'football') self.role = role def play(self): print("Player {} passes the ball to a striker".format(self.name)) This time the print statement is more specific, it says that the midfielder passes the ball to a striker instead of printing a generic message that applies to all types of players. Let’s execute this method on an object of type Midfielder in the same way we have done in the previous section: midfielder1 = Midfielder('James Midfielder', 'midfielder') midfielder1.play() The output is: $ python football.py Player James Midfielder passes the ball to a striker This time Python executes the method of the Midfielder child class because it’s implemented in it and it doesn’t execute the same method of the parent class (following the Method Resolution Order). Calling a Parent Method From a Child Class We have seen how the child class Midfielder was automatically resolving the play method from the parent class when it didn’t have an implementation for it. But, are there scenarios in which we might want to explicitly call a parent method from a child class even if the same method exists in the child class? Let’s find out! I want to change the code so that when I execute the play method in one of the child classes two messages are printed: - The first message says that the player starts running. - The second message describes the next action that our player takes. And in doing this we want to use the fact that the first message is already printed by the play method of the parent class and we want to avoid repeating it in the child classes: For example, let’s update the play method of the Midfielder class: class Midfielder(Player): def __init__(self, name, role): super().__init__(name, 'football') self.role = role def play(self): super().play() print("Player {} passes the ball to a striker".format(self.name)) Firstly, in the play method we use super() to call the play method of the parent class. And then we execute a print statement to show the second action taken by our midfielder. And here’s what we see when we run the play method on an object of type Midfielder: $ python football.py Player James Midfielder starts running Player James Midfielder passes the ball to a striker In this example I’m using Python 3. $ python --version Python 3.7.4 I’m wondering if this also works with Python 2… $ python2 --version $ python2 football.py Traceback (most recent call last): File "football.py", line 39, in midfielder1 = Midfielder('James Midfielder', 'midfielder') File "football.py", line 25, in __init__ super().__init__(name, 'football') TypeError: super() takes at least 1 argument (0 given) We can see an error when calling super() without arguments if we use Python 2. That’s because… In Python 2 the super() method requires additional arguments compared to Python 3. We also need to explicitly inherit our parent class from object as shown below. class Player(object): def __init__(self, name, sport): self.name = name self.sport = sport def play(self): print("Player {} starts running".format(self.name)) class Midfielder(Player): def __init__(self, name, role): super(Midfielder, self).__init__(name, 'football') self.role = role def play(self): super(Midfielder, self).play() print("Player {} passes the ball to a striker".format(self.name)) I will explain the exact rationale behind this in another article about the difference between old style and new style classes in Python. For now notice the following changes… The definition of the parent class now starts with: class Player(object): And the two calls to super take two arguments: the subclass in which super() is called and the instance of the subclass: super(Midfielder, self).__init__(name, 'football') super(Midfielder, self).play() In the next sections of this tutorial we will continue using the Python 3 syntax to call the super method. Difference Between isinstance and issubclass With Python Classes Let’s deepen our knowledge about Python classes in relation to inheritance. In this last section we will look at the difference between the isinstance and issubclass Python built-in functions. The difference between these two functions is explained in their name: - isinstance applies to instances. It allows to check the type of a class instance (or object). - issubclass applies to classes. It provides details about inheritance between classes. Let’s start with isinstance… The isinstance function takes two arguments in the following order: object and classinfo. It returns True if the object is an instance of classinfo or a subclass of it. Otherwise it returns False. Here is what it returns when we apply it to our midfielder1 object defined in the previous section: >>> print(isinstance(midfielder1, Midfielder)) True >>> print(isinstance(midfielder1, Player)) True As you can see the function returns True in both cases because midfielder1 is an instance of type Midfielder but also of type Player due to inheritance. And now let’s look at issubclass… The issubclass function takes two arguments: class and classinfo. It returns True if the class is a subclass of classinfo. Otherwise it returns False. We will apply it to the Midfielder and Player classes: >>> print(issubclass(Midfielder, Midfielder)) True >>> print(issubclass(Midfielder, Player)) True We already knew that Midfielder is a subclass of Player. But with the code above we have also learned that Midfielder is a subclass of Midfielder. A class is a subclass of itself. All clear? Conclusion We went through quite a lot in this article… You have learned the: - Basics about inheritance in Python. - Difference between Parent and Child classes. - Way to define methods in Child classes that override the same methods from the Parent classes. - Technique to call parent methods from child classes. - Difference between the Python built-in methods isinstance and issubclass. And you? How are you using inheritance in your Python programs? Let me know in the comments! Also to deepen your knowledge about Python classes have a look at this article about Python abstract classes. I’m a Tech Lead, Software Engineer and Programming Coach. I want to help you in your journey to become a Super Developer!
1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1 10.1 11.1 12.1 13.1 14.1 15.1 16.1 17.1 18.1 19.1 20.1 21.1 22.1 24.1 25.1 26.1 27.1 28.1 29.1 30.1 31.1 32.1 33.1 34.1 35.1 36.1 37.1 38.1 39.1 40.1 41.1 42.1 43.1 44.1 45.1 46.1 47.1 48.1 49.1 50.1 51.1 52.1 53.1 54.1 55.1 56.1 57.1 58.1 59.1 60.1 61.1 62.1 63.1 64.1 65.1 66.1 67.1 68.1 69.1 70.1 71.1 72.1 73.1 74.1 75.1 76.1 77.1 78.1 79.1 80.1 82.1 83.1 84.1 85.1 86.1 87.1 88.1 89.1 90.1 91.1 92.1 93.1 94.1 95.1 96.1 97.1 98.1 99.1 100.1 102.1 103.1 104.1 105.1 106.1 107.1 108.1 109.1 110.1 111.1 112.1 113.1 114.1 115.1 116.1 117.1 118.1 119.1 120.1 121.1 122.1 124.1 125.1 126.1 127.1 128.1 129.1 130.1 131.1 132.1 133.1 134.1 135.1 136.1 137.1 138.1 139.1 140.1 141.1 142.1 143.1 144.1 145.1 146.1 147.1 148.1 149.1 150.1 151.1 152.1 153.1
Arcade Türü Oyun Programlamayıve Bilgisayar Bilimleri Öğrenin Chapter 12: Sınıflara Giriş 12.1 Basit Sınıfların Tanımlanması ve Oluşturulması Programcı verinin çok sayıda ilgili parçasını fonksiyona aktarmak isterse, bunu sadece değişkenleri kullanarak yapmak zor olabilir. Daha iyi bir yol ise tüm bilgileri bir araya getiren bir veri yapısı tanımlayıp daha sonra bilgiye Address gibi bir isim vermektir. Bu, Python ve diğer modern dillerde sınıflar (class) kullanılarak kolayca yapılabilir. Bu kod, bir adresi tutan örnek bir sınıftır: class Address(): name="" line1="" line2="" city="" state="" zip="" Yukarıdaki kodta, Address sınıf ismidir. name ve city gibi sınıfta yer alan değişkenler sınıfın nitelikleri(attribute) ya da alanlarıdır(field). Fonksiyon tanımlama ile sınıf oluşturma arasındaki benzerliklere dikkat edin. Bu kod bir sınıfı tanımlar fakat aslında onun bir örneğini oluşturur. Kod bilgisauara bir adresin hangi alanlarının olacağını ve başlangıç değerlerinin ne olacağını söyler. Fonksiyonlardan ve değişkenlerden farklı olarak, sınıf isimleri büyük harfle başlamalıdır. Küçük harfle başlamak da mümkün olduğu halde, bu güzel bir gelenek olarak düşünülmemektedir. Programcılar sık sık sınıfları çizelge haline getirirler, ve bu ders için bir çizelge şu şekildedir: Sınıf ismi üstte ve her özellik onun altında isimleriyle listelenmektedir. Her özelliğin yanında string veya integer gibi veri türleri yazmaktadır. Kod bir adres bile belirlese, bir adresin oluşturulmadığına dikkat edin. Tıpkı fonksiyon gibi, fonksiyonun tanımlanmış olması onun oluşturulduğu anlamına gelmez. Sınıf oluşturmak ve alanları belirlemek için, alttaki örneğe bakın: # Adres oluştur homeAddress=Address() # Adresteki alanları belirle homeAddress.name="John Smith" homeAddress.line1="701 N. C Street" homeAddress.line2="Carver Science Building" homeAddress.city="Indianola" homeAddress.state="IA" homeAddress.zip="50125" address sınıfının bir örneği 9. satırda oluşturulmuştur. Sınıf isminin kullanıldığına ve parantezlerle devam ettiğine dikkat edin. Değişken ismi normal değişken adlandırma kurallarına uyacak şekilde her şey olabilir. Sınıfta alanları belirlemek için, program nokta operatörü kullanmak zorundadır. Bu operatör homeAddress ile alan arasındaki noktadır. Atamanın sol kısmı normal gibi görünmektedir. 12-17 arası astırlar her alana değer atarlar. Çok yaygın yapılan bir hata ise sınıflarla çalışırken değişken ismini belirtmeyi unutmaktır. Sadece bir address oluşturulduysa, bilgisayarın şehri "Indianola" pşaral belirlerken bu adresi kullanacağını varsaymak normaldir. Ancak bu durum böyle değildir. ıkinci bir adres de oluşturulabilir ve ikisinin de alanları kullanılabilir. Önceki örneklerin devamı olarak alttaki kodu inceleyin: # Başka bir adres oluştur vacationHomeAddress=Address() # Adreslerdeki alanları belirle vacationHomeAddress.name="John Smith" vacationHomeAddress.line1="1122 Main Street" vacationHomeAddress.line2="" vacationHomeAddress.city="Panama City Beach" vacationHomeAddress.state="FL" vacationHomeAddress.zip="32407" print ("Müşterinin ev adresi şu şehirde: "+homeAddress.city) print ("Yazlığı ise şurda: "+vacationHomeAddress.city) 19. satır yeni bir değişken ismine atanan ikinci bir adres oluşturuyor. 22-27 arası satırlar bu yeni sınıf örneği için alanları dolduruyor. 29. satır ev adresinin olduğu şehri gösteriyor, çünkü homeAddress nokta operatöründen önce gözüküyor. 30. satır yazlığın adresini gösteriyor, bunun sebebi de vacationHomeAddress nokta operatöründen önce gözüküyor. Yukarıdaki örneklerde, Address, sınıf olarak çağırılır çünkü o veri nesnesinin yeni bir sınıflandırmasını tanımlıyor. homeAddress ve vacationHomeAddress değişkenleri nesnelere(objects) tekabül ediyor çünkü onlar aslında Address sınıfının örneklerine tekabül ediyor. Nesne için basit bir tanım yapmak gerekirse o, sınıfın bir örneğidir. Çok miktarda veriyi bir sınıfın içerisinde alanlara koymak veriyi bir fonksiyonun içerisine ve dışarısına aktarmayı kolaylaştırıyor.Alttaki kodta, fonksiyon address'i bir parametre olarak alıyor ve onu ekrana yazdırıyor. address'in tüm alanlarındaki parametreleri ayrı ayrı aktarmak gerekli değildir. # Ekrana bir adres yazdır def printAddress(address): print (address.name) # Adreste 1. satır(line1) varsa, onu ekrana yazdır if( len(address.line1) > 0 ): print (address.line1) # Adreste 2. satır(line2) varsa, onu ekrana yazdır if( len(address.line2) > 0 ): print( address.line2 ) print( address.city+", "+address.state+" "+address.zip ) printAddress( homeAddress ) print() printAddress( vacationHomeAddress ) - Bu sınıfın bir örneğini oluşturacak ve niteliklerini belirleyecek bir kod yazın: class Dog(): age=0 name="" weight=0 - Bu sınıfın iki farklı örneğini oluşturan ve ikisine de nitelikleri belirleyen bir kod yazın: class Person(): name="" cellPhone="" email="" - Alttaki kod için, kodun çalışabilmesi için uygun sınıf isminde ve niteliklerde bir sınıf yazın. myBird = Bird() myBird.color="green" myBird.name="Sunny" myBird.breed="Sun Conure" - Basit bir 2 boyutlu oyunda bir karakteri temsil edecek bir sınıf oluşturun. Konum, isim ve güç niteliklerini dahil edin. - Alttaki kod çalışır, fakat doğru değildir. Programcı neyi yanlış yapmıştır? class Person: name="" money=0 nancy=Person() name="Nancy" money=100 - Koda biraz bakın. Çalışmıyor. Hatayı bulabilir misiniz? class Person: name="" money=0 bob = Person() print (bob.name,"has",money,"dollars.") - Hata düzeltilmiş olsa bile, program istenen sonucu yazdırmayacaktır: Bob has 0 dollars. Neden bu durum oluşuyor? 12.1.2 Metotlar Niteliklere ek olarak, sınıflar metotlara(methods) sahip olabilirler. Metot, sınıfın içerisinde var olan fonksiyona denir. Yukarıdaki tekrar kısmında 1. problemden Dog sınıfının örneği olan kodu genişletirsek, alttaki kod köpek havlaması için bir metot eklemektedir. class Dog(): age=0 name="" weight=0 def bark(self): print( "Hav!" ) Metot'un tanımlanması yukarıda 6 ve 7'nci satırlarda yapılmıştır. Bir sınıfta metot tanımlamaları nerdeyse tamamen bir fonksiyon tanımlaması gibi görünmektedir. Büyük farklılık ise parametre olarak self'in 6. satıra eklenmiş olmasıdır. Sınıfların içerisindeki bütün metotlarda ilk parametre self olmalıdır. Bu parametre, fonksiyon onu kullanmasa bile gereklidir. Burda sınıflar için metot oluştururken aklınızda tutmanız için önemli noktalar yer alıyor: - Nitelikler önce listelenmelidir, daha sonra metotlar gelir. - Bütün metotların ilk parametresi self olmalıdır. - Metot tanımlamaları tam bir sekme girintilenir. Metotlar, bir nesnedeki niteliklerin belirtilmesine benzer bir şekilde çağırılabilir. Alttaki kodu inceleyin. myDog = Dog() myDog.name="Spot" myDog.weight=20 myDog.age=3 myDog.bark() 9. satırda köpek(dog) oluşturuluyor. 11-13 satırlarında nesnenin nitelikleri belirleniyor. 14. satır bark (havlama) fonksiyonunu çağırıyor. bark fonksiyonu bir tane parametreye sahip olsa bile, self hiçbir şey aktarmaz. Sebebi ise ilk parametrenin dog nesnesinin kendisine bir referans olarak görülmesidir. Perde arkasında, Python şunun gibi görünen bir çağırma yapar: # Örnek, fakat gerçek anlamda geçerli değil Dog.bark(myDog) bark fonksiyonu herhangi bir niteliğe referans kurmak isterse, bunu self referans değişkenini kullanarak yapar. Örneğin, köpek havladığında köpeğin adını da yazacak şekilde Dog sınıfını değiştirebiliriz. Alttaki kodta, isim niteliğine nokta operatörü ve self referansı kullanılarak erişilebilir. def bark(self): print( "Woof says",self.name ) Nitelikler sıfatlardır, metotlar fiillerdir. Bu sınıf için çizim için alttakine bakılabilir: 12.1.3 Örnek: Top Sınıfı Bu, Python/Pygame'de kullanılarak bir top çizdirebilecek örnek kodtur. Tüm parametreleri bir sınıfta toplamak yönetimi daha kolay bir hale getirir. class Ball(): # --- Sınıf Nitelikleri --- # Topun konumu x=0 y=0 # Top vektörü change_x=0 change_y=0 # Top boyutu size=10 # Top rengi color=[255,255,255] # --- Sınıf Metotları --- def move(self): self.x += self.change_x self.y += self.change_y def draw(self, screen): pygame.draw.circle(screen, self.color, [self.x, self.y], self.size ) Altta, ana program döngüsünden önce top oluşturmak için yer alacak ve niteliklerini atayacak bir kod var: theBall = Ball() theBall.x = 100 theBall.y = 100 theBall.change_x = 2 theBall.change_y = 1 theBall.color = [255,0,0] Bu kod topu hareket ettirmek ve çizmek için ana döngünün içerisine gidecek: theBall.move() theBall.draw(screen) 12.2 Referanslar (References) Alttaki kodu bir inceleyin: class Person: name="" money=0 bob = Person() bob.name="Bob" bob.money=100 Kavramlar hakkında yaşanan sıkça rastlanan bir yanılgı ise nesnelerle çalışırken bob'un Person nesnesi olduğunu varsaymaktır. Durum böyle değildir. bob değişkeni Person nesnesine bir referanstır. Bu, örnek kodumuzun tamamlanması ve çalıştırılmasıyla gösterilebilir: nancy = bob nancy.name="Nancy" print(bob.name,"has",bob.money,"dollars.") print(nancy.name,"has",nancy.money,"dollars.") Eğer bob gerçekten bir nesne olsaydı, 9. satırda nesnenin bir kopyası oluşturulurdu ve iki nesne var olurdu. Programın çıktısı Bob ve Nancy'nin 100 dolara sahip olduğunu söylerdi. Fakat çalıştırdığımızda, program onun yerine şöyle bir çıktı veriyor: Nancy has 100 dollars. Nancy has 100 dollars. bob'un sakladığı şey ise nesnenin referansıdır. Referansın yanısıra, adres, işaretçi(pointer) ya da tanıtıcı değer(handle) olarak da çağırılabilir. Referans, nesnenin saklandığı yerin bilgisayar hafızasındaki adresidir. Bu adres, eğer yazdırılırsa, hegzadesimal(onaltılık) bir sayıdır ve 0x1e504 gibi bir şeye benzer. 9. satır çalıştırıldığında bu adresin işaret ettiği bütün nesne yerine sadece adres kopyalanır. 12.2.1 Fonksiyonlar ve Referanslar Alttaki kod önceden gösterilen diğer örneklerle benzerdir. 1. satır, sayı alan bir fonksiyon oluşturmuştur. money değişkeni gönderilen verinin kopyasıdır. Bu sayıya 100 eklemek 10. satırda bob.money içerisinde saklanan sayıyı değiştirmez. Bu nedenle, 13. satırdaki print ifadesi 200 değil, 100 yazdırır. def giveMoney1(money): money += 100 class Person: name="" money=0 bob = Person() bob.name="Bob" bob.money=100 giveMoney1(bob.money) print(bob.money) Alttaki eklenmiş koda bakın. Bu kod bob.money'in artmasına ve print ifadesinin 200 yazdırmasına neden olur. def giveMoney2(person): person.money += 100 giveMoney2(bob) print(bob.money) Bu neden çalıştı? Çünkü person nesnenin bir hafıza adresini içeriyor, nesnenin aslını içermiyor. Bu, banka hesap numarası olarak düşünülebilir. Fonksiyon banka hesap numarasının bir kopyasına sahip, bütün banka hesabının kopyasına değil. Yani, banka hesap numarasının kopyasına 100 dolar eklemek Bob'un banka hesabını da artırarak dengeliyor. Diziler de aynı yolla çalışır. Diziyi (listeyi) bir parametre olarak alan ve bu dizideki değerleri değiştiren fonksiyon, kodun oluşturduğu aynı diziyi de değiştirir. Dizinin adresi kopyalanmıştır, fakat bütün dizi kopyalanmamıştır. - kedi isimli bir sınıf oluşturun. Ona isim, renk ve ağırlık niteliklerini verin. Ayrıca miyav isimli bir metot verin. - Bu kedi sınıfının bir örneğini oluşturun, nitelikleri belirtin ve miyav metodunu çağırın. - Canavar isimli bir sınıf oluşturun. Ona bir isim niteliği ve güç için bir integer niteliği verin. miktar'ı bir parametre olarak alan ve verilen sayıda gücü azaltan gucuAzalt isimli bir metot oluşturun. Bu metodun içerisinde, güç sıfır olursa hayvanın öldüğünü ekrana yazdıran bir kod bulunsun. 12.3 Yapıcılar Python sınıfları sınıfın örneği her oluşturulduğunda çağırılan özel bir fonksiyona sahiptir. Örneğin, altta Dog bir sınıf ve devamında bu sınıfın örneğini oluşturan bir kod bulunuyor: class Dog() name="" myDog = Dog() Yapıcı (inşa edici,constructor) diye çağırılan bir fonksiyon ekleyerek bir programcı, sınıfın örneklendiği her seferde otomatik olarak çalışan bir kod ekleyebilir. Alttaki yapıcı kod örneğini inceleyin: class Dog(): name="" # Yapıcı # Bu tür bir nesne oluşturulduğunda çağırılır def __init__(self): print("Yeni bir köpek doğdu!") # Bu, köpeği oluşturur myDog = Dog() Yapıcı 6. satırda başlıyor. Yapıcının adı __init__ olmak zorundadır. Yapıcılar ilk parametre olarak self'i almak zorundadır. İstendiği takdirde, yapıcılar daha fazla parametreye sahip olabilir. Program çalıştırıldığında, şunu yazdıracaktır: Yeni bir köpek doğdu! 10. satırda Dog nesnesi oluşturulduğunda, __init__ fonksiyonu otomatik olarak çağırılır ve mesaj ekrana yazdırılır. Yapıcı bir fonksiyon nesnenin başlatılması ve verilerin ayarlanması için kullanılabilir. Örneğin, örnek kodta yer alan name niteliği dog nesnesi oluşturulduktan sonra boş bırakılmıştır. Peki ya programcı bir nesneyi varsayılan bir değerde bırakmayı isterse? Bazı nesneler oluşturuldukları anda değerlerinin olmasına gerek duyarlar. Yapıcı fonksiyon bunu gerçekleştirmek için kullanılabilir. Alttaki kodu inceleyin: class Dog(): name="" # Yapıcı # Bu tür bir nesne oluşturulduğunda çağırılır def __init__(self, newName): self.name = newName # Bu, köpeği oluşturur myDog = Dog("Spot") # Atamanın yapıldığını doğrulamak için ismi ekrana yazdır print(myDog.name) # Bu satır hata verecektir çünkü # içeriye bir isim gönderilmemiştir. herDog = Dog() 6. satırda program newName isimli ek bir parametre edinmiştir. Bu parametrenin değeri Dog sınıfında name niteliğini atamak için kullanılmıştır. Sık yapılan bir hata ise __init__ fonksiyonunun parametresine nitelik ile aynı ismi vermek ve değerlerinin otomatik olarak senkronize olacağını sanmaktır. Bu, gerçekleşmez. class Dog(): name="Rover" # Yapıcı # Bu tür bir nesne oluşturulduğunda çağırılır def __init__(self, name): # Bu "Rover" yazdıracaktır print(self.name) # Bu "Spot" yazdıracaktır print(name) # Bu Dog nesnesini oluşturur myDog = Dog("Spot") Önceki örnekte, ekrana yazdırılan iki farklı değişken var. name adlı değişken 5. satırda metodun bir parametresi olarak oluşturuluyor. Bu metot değişkeni metot bittiği anda silinir. Bu, name isimli nitelikle aynı ismi paylaştığı halde (aynı zamanda örnek değişkeni olarak da bilinir), o tamamen farklı bir değişkendir. self.name değişkeni Dog sınıfının bu özel örneğinin name niteliğini belirtir. Dog sınıfının bu örneği var olduğu müddetçe o da var olacaktır. Bu tekrar için boş çalışma kağıdını indirin: [Microsoft Word DOCX] [Microsoft Word DOC] [PDF] - Sınıf isimleri büyük harfle mi küçük harfle mi başlamalıdır? - Metot isimleri büyük harfle mi küçük harfle mi başlamalıdır? - Nitelik isimleri büyük harfle mi küçük harfle mi başlamalıdır? - Bir sınıfta ilk olarak nitelikler mi metotlar mı listelenmelidir? - Referansın diğer isimleri nelerdir? - Örnek değişkenin diğer ismi nedir? - Sınıfın örneği için kullanılan isim nedir? - Star isimli, her oluşturulduğunda ekrana “Bir yıldız doğdu!” yazdıran bir sınıf oluşturun. - Güç ve isim için nitelikleri barındıran Canavar isimli bir sınıf oluşturun. Bu sınıfa gönderilen parametrelere göre nesnenin gücünü ve ismini atayan bir yapıcı fonksiyon ekleyin. 12.4 Miras (Kalıtım, Inheritance) Sınıfları ve nesneleri kullanmanın bir başka güçlü özelliği miras alma olanağına imkan sağlamalarıdır. Bir sınıf oluşturup bir üst sınıf(ebeveyn)tan tüm nitelikleri ve metotları miras almak mümkündür. Örneğin, bir program Person isimli ve bir kişi için gerekli tüm niteliklere sahip bir sınıf oluşturabilir. Program daha sonra, bu alanlardan miras alan alt sınıflar(çocuklar) oluşturabilir. Bu alt sınıflar daha sonra miras aldıkları sınıfın özellik ve metotlarına ihtiyaçlarına karşılık gelen alanları ve metotları ekleyebilir. Bir ebeveyn sınıf daha genel olmalıdır, alt sınıfın özet versiyonu olmalıdır. Örneği, ana sınıf bir Hayvan olabilirken, alt sınıf bir Köpek olabilir ve bu alt sınıf da Pıtır isimli bir alt sınıfa sahip olabilir. Bu şekilde bir çocuktan ebeveyne bağlantı bir ilişki olarak adlandırılır. Örneğin, yunus bir memeli ailesindendir. Bu ters yönde çalışmaz. Bir memeli hayvan yunus olmak zorunda değildir. Yani Yunus sınıfı asla Memeli sınıfının ebeveyni olmak zorunda değildir. Aynı şekilde, Masa sınıfı da Sandalye sınıfının bir alt sınıfı olmak zorunda değildir çünkü sandalye bir masa değildir. class Person(): name="" class Calisan(Person): job_title="" class Musteri(Person): email="" johnSmith = Person() johnSmith.name = "John Smith" janeEmployee = Calisan() janeEmployee.name = "Jane Employee" janeEmployee.job_title = "Web Developer" bobCustomer = Musteri() bobCustomer.name = "Bob Customer" bobCustomer.email = "send_me@spam.com" 4. ve 7. satırda Person'u parantezlerin arasına alarak, programcı bilgisayara Person'un hem Calisan hem de Musteri sınıflarının ebeveyni olduğunu söylemiştir. Bu programa 14. ve 18. satırlarda name niteliğini atama olanağı sağlamıştır. Ayrıca metotlar da miras alınır. Alttaki kod 3 kez “Kişi oluşturuldu” yazdıracaktır çünkü müşteri ve çalışan sınıfları ebeveyn sınıftan yapıcı fonksiyonu miras alır: class Person(): name="" def __init__(self): print("Kişi oluşturuldu") class Calisan(Person): job_title="" class Musteri(Person): email="" johnSmith = Person() janeEmployee = Calisan() bobCustomer = Musteri() Farklı bir işlevsellik sağlamak için metotlar çocuk sınıf yüzünden iptal edilebilir. Alttaki kodta, çocuk sınıflar kendi yapıcılarına sahiptir, yani ebeveynin sınıfı çalışmayacaktır: class Person(): name="" def __init__(self): print("Person created") class Calisan(Person): job_title="" def __init__(self): print("Çalışan oluşturuldu") class Musteri(Person): email="" def __init__(self): print("Müşteri oluşturuldu") johnSmith = Person() janeEmployee = Calisan() bobCustomer = Musteri() Programcı hem ebeveyn hem de çocuk sınıfının metotlarını çalıştırmak isterse, çocuk direk ebeveynin metodunu çağırabilir: class Person(): name="" def __init__(self): print("Person created") class Calisan(Person): job_title="" def __init__(self): Person.__init__(self) print("Çalışan oluşturuldu") class Musteri(Person): email="" def __init__(self): Person.__init__(self) print("Müşteri oluşturuldu") johnSmith = Person() janeEmployee = Calisan() bobCustomer = Musteri() Alttaki programı oluşturun. Onu kodlamadan önce yazmayı deneyin. Bunu yapmak için boş bir çalışma kağıdı indirin: [Microsoft Word DOCX] [Microsoft Word DOC] [PDF] - Hayvan isimli bir sınıf oluşturan kod yazın: - isim adlı bir nitelik ekleyin. - Hayvan sınıfına yemekye() adlı ve "Munch munch" yazdıran bir metot ekleyin. - Hayvan sınıfına gurultuYap() isimli bir metot ekleyin ve bu metodun “[hayvan ismi] gırrr dedi.” yazmasını sağlayın. - Hayvan sınıfına “Bir hayvan doğdu.” yazdıran yapıcı fonksiyon ekleyin. - Kedi isimli bir sınıf: - Hayvan sınıfını ebeveyn yapın. - Kedi için “[hayvan ismi] miyav dedi.” yazdıran bir gurultuYap() metodu ayarlayın. - Kedi için “Bir kedi doğdu.” yazdıran ve ebeveyn yapıcı fonksiyonunu çağıdan bir yapıcı fonksiyon yazın. - Kopek isimli bir sınıf - Hayvan sınıfını ebeveyn yapın. - Kopek için “[hayvan ismi] hav dedi.” yazdıran bir gurultuYap() metodu ayarlayın. - Kopek için “Bir köpek doğdu.” yazdıran ve ebeveyn yapıcı fonksiyonunu çağıdan bir yapıcı fonksiyon yazın. - Şunları içeren bir ana program yapın: - Bir kedi, iki köpek ve bir hayvan oluşturan kod. - Her hayvan için isim belirleyin. - yemekye() ve gurultuYap() metotlarını her hayvan için çağıran bir kod. You are not logged in. Log in here and track your progress. English version by Paul Vincent Craven Spanish version by Antonio Rodríguez Verdugo Russian version by Vladimir Slav Turkish version by Güray Yildirim Portuguese version by Armando Marques Sobrinho and Tati Carvalho Dutch version by Frank Waegeman Hungarian version by Nagy Attila Finnish version by Jouko Järvenpää French version by Franco Rossi Korean version by Kim Zeung-Il Chinese version by Kai Lin