http___programarcadegames.com_index.php_chapter_introduction_to_classes_lang_tr_1.xml
1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1 11.1 12.1 12.2 13.1 13.2 14.1 15.1 16.1 17.1 18.1 19.1 20.1 21.1 21.2 22.1 23.1 24.1 25.1 25.2 25.3 25.4 26.1 27.1 28.1 29.1 30.1 30.2 30.3 31.1 32.1 32.2 32.3 33.1 34.1 35.1 36.1 37.1 38.1 38.2 39.1 39.2 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 70.1 71.1 72.1 73.1 73.2 73.3 74.1 75.1 76.1 77.1 77.2 78.1 79.1 79.2 80.1 81.1 82.1 82.2 83.1 84.1 85.1 86.1 87.1 88.1 88.2 89.1 89.2 90.1 91.1 92.1 93.1 94.1 95.1 96.1 97.1 97.2 99.1 100.1 101.1 102.1 103.1 104.1 105.1 106.1 107.1 108.1 109.1 110.1 110.2 111.1 112.1 113.1 114.1 115.1 116.1 116.2 117.1 118.1 119.1 120.1 121.1 122.1 123.1 124.1 125.1 125.2 125.3 126.1 127.1 128.1 129.1 129.2 130.1 131.1 131.2 132.1 133.1 134.1 135.1 136.1 136.2 137.1 138.1 139.1 140.1 140.2 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 155.2 156.1 157.1 158.1 159.1 160.1 160.2 160.3 161.1 162.1 163.1 163.2 164.1 165.1 166.1 167.1 167.2 167.3 168.1 169.1 170.1 171.1 172.1 173.1 174.1 175.1 176.1 177.1 178.1 179.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 197.2 197.3 198.1 198.2 198.3 198.4 199.1 200.1 201.1 202.1 202.2 203.1 204.1 205.1 205.2 205.3 206.1 207.1 208.1 209.1 210.1 211.1 212.1 213.1 214.1 215.1 216.1 217.1 218.1 219.1 220.1 221.1 222.1 223.1 224.1 225.1 226.1 226.2 227.1 227.2 227.3 227.4 228.1 229.1 230.1 231.1 231.2 231.3 232.1 233.1 234.1 235.1 236.1 237.1 238.1 239.1 240.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 255.2 256.1 256.2 256.3 257.1 257.2 258.1 259.1 260.1 261.1 262.1 263.1 263.2 264.1 265.1 266.1 267.1 267.2 267.3 268.1 269.1 270.1 271.1 272.1 272.2 273.1 274.1 275.1 275.2 276.1 276.2 276.3 277.1 278.1 279.1 280.1 281.1 283.1 284.1 286.1 287.1 288.1 289.1 290.1 291.1 292.1 293.1 294.1 295.1 296.1 297.1 298.1 299.1 300.1 301.1 302.1 303.1 304.1 304.2 305.1 306.1 307.1 307.2 307.3 308.1 309.1 310.1 311.1 312.1 313.1 314.1 315.1 316.1 316.2 317.1 318.1 319.1 320.1 321.1 321.2 323.1 324.1 325.1 325.2 325.3 326.1 327.1 328.1 329.1 330.1 331.1 332.1 333.1 334.1 335.1 336.1 337.1 338.1 339.1 340.1 341.1 342.1 343.1 344.1 344.2 345.1 345.2 346.1 346.2 347.1 348.1 348.2 349.1 350.1 351.1 352.1 353.1 354.1 355.1 356.1 357.1 358.1 358.2 360.1 361.1 361.2 361.3 362.1 362.2 362.3 363.1 363.2 363.3 364.1 364.2 365.1 365.2 366.1 367.1 368.1 369.1 370.1 371.1 373.1 376.1 378.1 378.2 379.1 380.1 381.1 382.1 383.1 384.1 384.2 386.1 389.1 391.1 392.1 392.2 392.3 393.1 394.1 395.1 396.1 397.1 400.1 401.1 401.2 401.3 403.1 405.1 406.1 408.1 409.1 410.1 410.2 410.3 411.1 412.1 413.1 414.1 415.1 416.1 417.1 417.2 418.1 419.1 420.1 421.1 422.1 423.1 425.1 426.1 428.1 429.1 430.1 431.1 433.1 434.1 435.1 436.1 437.1 437.2 438.1 438.2 438.3 439.1 440.1 441.1 441.2 442.1 443.1 444.1 445.1 446.1 447.1 448.1 449.1 450.1 451.1 452.1 453.1 454.1 455.1 456.1 457.1 458.1 458.2 460.1 462.1 463.1 464.1 466.1 467.1 468.1 470.1 471.1 471.2 472.1 472.2 472.3 473.1 474.1 476.1 476.2 477.1 478.1 479.1 480.1 481.1 482.1 482.2 483.1 484.1 484.2 485.1 486.1 487.1 488.1 489.1 490.1 491.1 492.1 493.1 494.1 495.1 496.1 497.1 498.1 499.1 500.1 501.1 502.1 503.1 504.1 505.1 506.1 506.2 507.1 508.1 509.1 510.1 511.1 512.1 512.2 513.1 514.1 514.2 515.1 516.1 517.1 518.1 519.1 519.2 520.1 520.2 521.1 522.1 523.1 525.1 526.1 527.1 527.2 527.3 528.1 529.1 530.1 531.1 533.1 533.2 534.1 535.1 535.2 536.1 537.1 538.1 539.1 539.2 540.1 541.1 542.1 543.1 544.1 545.1 545.2 545.3 546.1 548.1 549.1 550.1 551.1 552.1 553.1 554.1 554.2 555.1 556.1 557.1 558.1 559.1 560.1 561.1 562.1 563.1 564.1 565.1 566.1 567.1 567.2 568.1 568.2 569.1 570.1 571.1 572.1 573.1 574.1 575.1 576.1 577.1 578.1 579.1 580.1 581.1 582.1 583.1 584.1 584.2 585.1
Table of Contents - What Is Object-Oriented Programming (OOP)? - Class and Object - Class or Static Variables and Instance Variables - Class methods, static methods and instance methods - Inheritance, Polymorphism, Abstraction, Encapsulation - Methods Overloading and Method Overriding - Access Modifiers - Public, Private and Protected - Getter, Setter and Property What Is Object-Oriented Programming (OOP)? Python is a multi-paradigm programming language. Meaning, it supports different programming approach. One of the popular approach to solve a programming problem is by creating objects. This is known as Object-Oriented Programming (OOP). An object has two characteristics: - attributes - behavior Let's take an example: Parrot is an object, - name, age, color are attributes - singing, dancing are behavior The concept of OOP in Python focuses on creating reusable code. This concept is also known as DRY (Don't Repeat Yourself). In Python, the concept of OOP follows some basic principles: Class A class is a blueprint for the object. We can think of class as an sketch of a parrot with labels. It contains all the details about the name, colors, size etc. Based on these descriptions, we can study about the parrot. Here, parrot is an object. The example for class of parrot can be : class Parrot: pass Here, we use class keyword to define an empty class Parrot. From class, we construct instances. An instance is a specific object created from a particular class. Object An object (instance) is an instantiation of a class. When class is defined, only the description for the object is defined. Therefore, no memory or storage is allocated. The example for object of parrot class can be: obj = Parrot() Here, obj is object of class Parrot. Class or Static Variable and Instance Variable Class or static variables are shared by all objects. Instance or non-static variables are different for different objects (every object has a copy of it). All variables which are assigned a value in class declaration and classmethod are class variables. And variables which are assigned values inside instance methods are instance variables. Example class CSStudent: stream = 'cse' # Class or Static Variable def __init__(self,name,roll): self.name = name # Instance Variable self.roll = roll # Instance Variable # Objects of CSStudent class a = CSStudent('Nitin', 1) b = CSStudent('Kanchan', 2) print(a.stream) # prints "cse" print(b.stream) # prints "cse" print(a.name) # prints "Nitin" print(b.name) # prints "Kanchan" print(a.roll) # prints "1" print(b.roll) # prints "2" # Class variables can be accessed using class # name also print(CSStudent.stream) # prints "cse" Class, Static and Instance Method Let’s begin by writing a (Python 3) class that contains simple examples for all three method types class MyClass: def method(self): return 'instance method called', self @classmethod def classmethod(cls): return 'class method called', cls @staticmethod def staticmethod(): return 'static method called' Instance Methods The first method on MyClass, called method, is a regular instance method. That’s the basic, no-frills method type you’ll use most of the time. You can see the method takes one parameter, self, which points to an instance of MyClass when the method is called (but of course instance methods can accept more than just one parameter). Through the self parameter, instance methods can freely access attributes and other methods on the same object. This gives them a lot of power when it comes to modifying an object’s state. Not only can they modify object state, instance methods can also access the class itself through the self.__class__ attribute. This means instance methods can also modify class state. Class Methods Let’s compare that to the second method, MyClass.classmethod. I marked this method with a @classmethod decorator to flag it as a class method. Instead of accepting a self parameter, class methods take a cls¬†parameter that points to the class‚ÄĒand not the object instance‚ÄĒwhen the method is called. Because the class method only has access to this cls argument, it can’t modify object instance state. That would require access to self. However, class methods can still modify class state that applies across all instances of the class. Static Methods The third method, MyClass.staticmethod was marked with a @staticmethod decorator to flag it as a static method. This type of method takes neither a self nor a cls parameter (but of course it’s free to accept an arbitrary number of other parameters). Therefore a static method can neither modify object state nor class state. Static methods are restricted in what data they can access - and they’re primarily a way to namespace your methods. Let’s See Them In Action! Instance Methods >>> obj = MyClass() >>> obj.method() ('instance method called',  ) This confirmed that method (the instance method) has access to the object instance (printed as ) via the self argument. When the method is called, Python replaces the self argument with the instance object, obj. We could ignore the syntactic sugar of the dot-call syntax ( obj.method()) and pass the instance object manually to get the same result: >>> MyClass.method(obj) ('instance method called',  ) Can you guess what would happen if you tried to call the method without first creating an instance? By the way, instance methods can also access the class itself through the self.__class__ attribute. This makes instance methods powerful in terms of access restrictions - they can modify state on the object instance and on the class itself. Class Methods >>> obj.classmethod() ('class method called',  ) Calling classmethod() showed us it doesn’t have access to the object, but only to the object, representing the class itself (everything in Python is an object, even classes themselves). Notice how Python automatically passes the class as the first argument to the function when we call MyClass.classmethod(). Calling a method in Python through the dot syntax triggers this behavior. The self parameter on instance methods works the same way. Please note that naming these parameters self and cls is just a convention. You could just as easily name them the_object and the_class and get the same result. All that matters is that they’re positioned first in the parameter list for the method. Static Methods >>> obj.staticmethod() 'static method called' Did you see how we called staticmethod() on the object and were able to do so successfully? Some developers are surprised when they learn that it’s possible to call a static method on an object instance. Behind the scenes Python simply enforces the access restrictions by not passing in the self or the cls argument when a static method gets called using the dot syntax. This confirms that static methods can neither access the object instance state nor the class state. They work like regular functions but belong to the class’s (and every instance’s) namespace. Now, let’s take a look at what happens when we attempt to call these methods on the class itself - without creating an object instance beforehand >> MyClass.classmethod() ('class method called',  ) >> MyClass.staticmethod() 'static method called' >> MyClass.method() TypeError: unbound method method() must be called with MyClass instance as first argument (got nothing instead) We were able to call classmethod() and staticmethod() just fine, but attempting to call the instance method method() failed with a TypeError. And this is to be expected ‚ÄĒ this time we didn‚Äôt create an object instance and tried calling an instance function directly on the class blueprint itself. This means there is no way for Python to populate the¬† self argument and therefore the call fails. Class method vs Static Method - A class method takes cls as first parameter while a static method needs no specific parameters. - A class method can access or modify class state while a static method can’t access or modify it. - In general, static methods know nothing about class state. They are utility type methods that take some parameters and work upon those parameters. On the other hand class methods must have class as parameter. - We use @classmethod decorator in python to create a class method and we use @staticmethod decorator to create a static method in python. When to use what? - We generally use class method to create factory methods. Factory methods return class object ( similar to a constructor ) for different use cases. - We generally use static methods to create utility functions. Inheritance, Polymorphism, Encapsulation, Abstraction Inheritance Inheritance is a way of creating new class for using details of existing class without modifying it. The newly formed class is a derived class (or child class). Similarly, the existing class is a base class (or parent class). # parent class class Bird: def __init__(self): print("Bird is ready") def whoisThis(self): print("Bird") def swim(self): print("Swim faster") # child class class Penguin(Bird): def __init__(self): # call super() function print("Penguin is ready") def whoisThis(self): print("Penguin") def run(self): print("Run faster") peggy = Penguin() peggy.whoisThis() peggy.swim() peggy.run() When we run this program, the output will be: # Output Bird is ready Penguin is ready Penguin Swim faster Run faster In the above program, we created two classes i.e. Bird (parent class) and Penguin (child class). The child class inherits the functions of parent class. We can see this from swim()method. Again, the child class modified the behavior of parent class. We can see this from whoisThis() method. Furthermore, we extend the functions of parent class, by creating a new run() method. Additionally, we use super() function before __init__() method. This is because we want to pull the content of __init__() method from the parent class into the child class. Encapsulation Using OOP in Python, we can restrict access to methods and variables. This prevent data from direct modification which is called encapsulation. In Python, we denote private attribute using underscore as prefix i.e single “_ “ or double “ __“. class Computer: def __init__(self): self.__maxprice = 900 def sell(self): print("Selling Price: {}".format(self.__maxprice)) def setMaxPrice(self, price): self.__maxprice = price c = Computer() c.sell() # change the price c.__maxprice = 1000 c.sell() # using setter function c.setMaxPrice(1000) c.sell() When we run this program, the output will be: # Output Selling Price: 900 Selling Price: 900 Selling Price: 1000 In the above program, we defined a class Computer. We use __init__() method to store the maximum selling price of computer. We tried to modify the price. However, we can’t change it because Python treats the __maxprice as private attributes. To change the value, we used a setter function i.e setMaxPrice() which takes price as parameter. Polymorphism Polymorphism is an ability (in OOP) to use common interface for multiple form (data types). Suppose, we need to color a shape, there are multiple shape option (rectangle, square, circle). However we could use same method to color any shape. This concept is called Polymorphism. class Parrot: def fly(self): print("Parrot can fly") def swim(self): print("Parrot can't swim") class Penguin: def fly(self): print("Penguin can't fly") def swim(self): print("Penguin can swim") # common interface def flying_test(bird): bird.fly() #instantiate objects blu = Parrot() peggy = Penguin() # passing the object flying_test(blu) flying_test(peggy) When we run above program, the output will be: # Output Parrot can fly Penguin can't fly In the above program, we defined two classes Parrot and Penguin. Each of them have common method fly() method. However, their functions are different. To allow polymorphism, we created common interface i.e flying_test() function that can take any object. Then, we passed the objects blu and peggy in the flying_test() function, it ran effectively. Abstraction Abstract classes Force a class to implement methods. Abstract classes can contain abstract methods: methods without an implementation. Objects cannot be created from an abstract class. A subclass can implement an abstract class. Abstract methods But why? If you have many objects of a similar type, you can call them in a similar fashion. Imagine having classes like Truck, Car and Bus. They would all have methods like Start, Stop, Accelerate. An abstract class (Automobile) can define these abstract methods. truck.start() truck.drive() bus.start() bus.drive() When a new class is added, a developer does not need to look for methods to implement. He/she can simply look at the abstract class. If one of the sub classes (Truck, Car, Bus) misses an implementation, Python automatically throws an error. Abstract class example Create an abstract class: AbstractAnimal. In the abstract class we only define the methods without an implementation. You can then create concrete classes: classes containing an implementation. Let’s create a class Duck which implements the AbstractAnimal. We use the same methods, but now add an implementation. import abc class AbstractAnimal(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def walk(self): @abc.abstractmethod def talk(self): class Duck(AbstractAnimal): name = '' def __init__(self, name): print('duck created.') self.name = name def walk(self): print('walks') def talk(self): print('quack') obj = Duck('duck1') obj.talk() obj.walk() # Output Traceback (most recent call last): File "abst.py", line 27, in obj = Duck('duck1') TypeError: Can't instantiate abstract class Duck with abstract methods walk If we forget to implement one of the abstract methods, Python will throw an error. This is how you can force classes to have methods. Those methods need to be defined in the abstract class. Method Overloading & Method Overriding Method Overloading Method overloading refers to the property of a method to behave in different ways depending upon the number or types of the parameters. Take a look at a very simple example of method overloading. Execute the following script: # Creates class Car class Car: def start(self, a, b=None): if b is not None: print (a + b) else: print (a) In the script above, if the start() method is called by passing a single argument, the parameter will be printed on the screen. However, if we pass 2 arguments to the start() method, it will add both the arguments and will print the result of the sum. Let's try with single argument first: car_a = Car() car_a.start(10) In the output, you will see 10. Now let's try to pass 2 arguments: In the output, you will see 30. Method Overriding Method overriding refers to having a method with the same name in the child class as in the parent class. The definition of the method differs in parent and child classes but the name remains the same. Let's take a simple example method overriding in Python. # Create Class Vehicle class Vehicle: def print_details(self): print("This is parent Vehicle class method") # Create Class Car that inherits Vehicle class Car(Vehicle): def print_details(self): print("This is child Car class method") # Create Class Cycle that inherits Vehicle class Cycle(Vehicle): def print_details(self): print("This is child Cycle class method") # Class Cycle can also be imlemented like this for showing overriding class Cycle(Vehicle,Car): pass In the script above the Car and Cycle classes inherit the Vehicle class. The vehicle class has print_details() method, which is overridden by the child classes. Now if you call the print_details() method, the output will depend upon the object through which the method is being called. Execute the following script to see this concept in action: car_a = Vehicle() car_a. print_details() car_b = Car() car_b.print_details() car_c = Cycle() car_c.print_details() The output will look like this: This is parent Vehicle class method This is child Car class method This is child Cycle class method You can see that the output is different, although the print_details() method is being called through derived classes of the same base class. However, since the child classes have overridden the parent class method, the methods behave differently. Access Modifiers - Public, Private and Protected Classical object-oriented languages, such as C++ and Java, control the access to class resources by public, private and protected keywords. Private members of a class are denied access from the environment outside the class. They can be handled only from within the class. Public members (generally methods declared in a class) are accessible from outside the class. The object of the same class is required to invoke a public method. This arrangement of private instance variables and public methods ensures the principle of data encapsulation. Protected members of a class are accessible from within the class and are also available to its sub-classes. No other environment is permitted access to it. This enables specific resources of the parent class to be inherited by the child class. Python doesn't have any mechanism that effectively restricts access to any instance variable or method. Python prescribes a convention of prefixing the name of the variable/method with single or double underscore to emulate the behaviour of protected and private access specifiers. All members in a Python class are public by default. Any member can be accessed from outside the class environment. Example: Public Attributes class employee: def __init__(self, name, sal): self.name=name self.salary=sal You can access employee class's attributes and also modify their values, as shown below. >>> e1.salary >>> e1.salary Python's convention to make an instance variable protected is to add a prefix _ (single underscore) to it. This effectively prevents it to be accessed, unless it is from within a sub-class. Example: Protected Attributes class employee: def __init__(self, name, sal): self._name=name # protected attribute self._salary=sal # protected attribute In fact, this doesn't prevent instance variables from accessing or modifyingthe instance. You can still perform the following operations: >>> e1._salary >>> e1._salary Hence, the responsible programmer would refrain from accessing and modifying instance variables prefixed with _ from outside its class. Similarly, a double underscore __ prefixed to a variable makes it private. It gives a strong suggestion not to touch it from outside the class. Any attempt to do so will result in an AttributeError: Example: Private Attributes class employee: def __init__(self, name, sal): self.__name=name # private attribute self.__salary=sal # private attribute AttributeError: 'employee' object has no attribute '__salary' Python performs name mangling of private variables. Every member with double underscore will be changed to _object._class__variable. If so required, it can still be accessed from outside the class, but the practice should be refrained. >>> e1._Employee__salary >>> e1._Employee__salary=20000 >>> e1._Employee__salary Getter, Setter and Property An Example To Begin With Let us assume that you decide to make a class that could store the temperature in degree Celsius. It would also implement a method to convert the temperature into degree Fahrenheit. One way of doing this is as follows. class Celsius: def __init__(self, temperature = 0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 We could make objects out of this class and manipulate the attribute temperature as we wished. Try these on Python shell. >>> # create new object >>> man = Celsius() >>> # set temperature >>> man.temperature = 37 >>> # get temperature >>> man.temperature >>> # get degrees Fahrenheit >>> man.to_fahrenheit() The extra decimal places when converting into Fahrenheit is due to the floating point arithmetic error (try 1.1 + 2.2 in the Python interpreter). Whenever we assign or retrieve any object attribute like temperature, as show above, Python searches it in the object's __dict__ dictionary. {'temperature': 37} Therefore, man.temperature internally becomes man.__dict__['temperature']. Now, let's further assume that our class got popular among clients and they started using it in their programs. They did all kinds of assignments to the object. One fateful day, a trusted client came to us and suggested that temperatures cannot go below -273 degree Celsius (students of thermodynamics might argue that it's actually -273.15), also called the absolute zero. He further asked us to implement this value constraint. Being a company that strive for customer satisfaction, we happily heeded the suggestion and released version 1.01 (an upgrade of our existing class). Using Getters and Setters An obvious solution to the above constraint will be to hide the attribute temperature (make it private) and define new getter and setter interfaces to manipulate it. This can be done as follows. class Celsius: def __init__(self, temperature = 0): self.set_temperature(temperature) def to_fahrenheit(self): return (self.get_temperature() * 1.8) + 32 # new update def get_temperature(self): return self._temperature def set_temperature(self, value): if value < -273: raise ValueError("Temperature below -273 is not possible") self._temperature = value We can see above that new methods get_temperature() and set_temperature() were defined and furthermore, temperature was replaced with _temperature. An underscore (_) at the beginning is used to denote private variables in Python. Traceback (most recent call last): ValueError: Temperature below -273 is not possible >>> c = Celsius(37) >>> c.get_temperature() >>> c.set_temperature(10) >>> c.set_temperature(-300) Traceback (most recent call last): ValueError: Temperature below -273 is not possible This update successfully implemented the new restriction. We are no longer allowed to set temperature below -273. Please note that private variables don't exist in Python. There are simply norms to be followed. The language itself don't apply any restrictions. >>> c._temperature = -300 >>> c.get_temperature() But this is not of great concern. The big problem with the above update is that, all the clients who implemented our previous class in their program have to modify their code from obj.temperature to obj.get_temperature() and all assignments like obj.temperature = val to obj.set_temperature(val). This refactoring can cause headaches to the clients with hundreds of thousands of lines of codes. All in all, our new update was not backward compatible. This is where property comes to rescue. The Power of @property The pythonic way to deal with the above problem is to use property. Here is how we could have achieved it. class Celsius: def __init__(self, temperature = 0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 def get_temperature(self): print("Getting value") return self._temperature def set_temperature(self, value): if value < -273: raise ValueError("Temperature below -273 is not possible") print("Setting value") self._temperature = value temperature = property(get_temperature,set_temperature) And, issue the following code in shell once you run it. >>> c = Celsius() We added a print() function inside get_temperature() and set_temperature() to clearly observe that they are being executed. The last line of the code, makes a property object temperature. Simply put, property attaches some code ( get_temperature and set_temperature) to the member attribute accesses ( temperature). Any code that retrieves the value of temperature will automatically call get_temperature()instead of a dictionary (__dict__) look-up. Similarly, any code that assigns a value to temperature will automatically call set_temperature(). This is one cool feature in Python. We can see above that set_temperature() was called even when we created an object. Can you guess why? The reason is that when an object is created , __init__() method gets called. This method has the line self.temperature = temperature. This assignment automatically called set_temperature(). >>> c.temperature Getting value Similarly, any access like c.temperature automatically calls get_temperature(). This is what property does. Here are a few more examples. >>> c.temperature = 37 Setting value >>> c.to_fahrenheit() Getting value By using property, we can see that, we modified our class and implemented the value constraint without any change required to the client code. Thus our implementation was backward compatible and everybody is happy. Finally note that, the actual temperature value is stored in the private variable _temperature. The attribute temperature is a property object which provides interface to this private variable. Digging Deeper into Property In Python, property() is a built-in function that creates and returns a property object. The signature of this function is property(fget=None, fset=None, fdel=None, doc=None) where, fget is function to get value of the attribute, fset is function to set value of the attribute, fdel is function to delete the attribute and doc is a string (like a comment). As seen from the implementation, these function arguments are optional. So, a property object can simply be created as follows. >>> property() A property object has three methods, getter(), setter(), and deleter() to specify fget, fset and fdel at a later point. This means, the line temperature = property(get_temperature,set_temperature) could have been broken down as # make empty property temperature = property() # assign fget temperature = temperature.getter(get_temperature) # assign fset temperature = temperature.setter(set_temperature) These two pieces of codes are equivalent. Programmers familiar with decorators in Python can recognize that the above construct can be implemented as decorators. We can further go on and not define names get_temperature and set_temperature as they are unnecessary and pollute the class namespace. For this, we reuse the name temperature while defining our getter and setter functions. This is how it can be done. class Celsius: def __init__(self, temperature = 0): self._temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 @property def temperature(self): print("Getting value") return self._temperature @temperature.setter def temperature(self, value): if value < -273: raise ValueError("Temperature below -273 is not possible") print("Setting value") self._temperature = value The above implementation is both, simple and recommended way to make properties. You will most likely encounter these types of constructs when looking for property in Python. Well that's it for today.
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