Download presentation
Presentation is loading. Please wait.
1
Lecture 18 Python OOP
2
Python Classes class BankAccount: def __init__(self): self._balance = 0 def withdraw(self, amount): self._balance -= amount def deposit(self, amount): self._balance += amount def get_balance(self): return self._balance Shell (note that the class file was in the working directory from which I ran idle): >>> from bank_account import BankAccount >>> a = BankAccount() >>> a.deposit(500) >>> a.get_balance() 500 >>> b = BankAccount() >>> b.get_balance() >>> b._balance >>> a.withdraw(100) 400
3
__init__ __init__ is called as soon as an object is created. It is not technically a constructor, since the object already exists. However, it does the same kind of initialization work you would do in a constructor. Some sources do use the term "constructor" for __init__. If there is no need for any initialization (the type of case in which you would use an implicit constructor in Java), you can omit __init__. There is a default do-nothing __init__. Functions with names that begin and end with double underscores ("dunder methods") are hooks, methods that are called automatically in certain circumstances and can be overridden to provide customized behavior.
4
Python Classes Class member functions are called methods The first argument of every class method, including __init__, is always a reference to the current instance of the class. By convention, this argument is always named self. In the __init__ method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called. Although you need to specify self explicitly when defining the method, you do not specify it when calling the method; Python will add it for you automatically. self is equivalent to the this pointer in C-family languages. Methods can create instance variables on the fly, without declaration outside the method, because the self. gives them class scope. A single underscore leading a variable name marks the variable as intended to be private. Python does not enforce encapsulation very rigorously; note that I was able to get directly to _balance in the shell. The term attribute is used to refer to anything that is part of an object, either a data value or a function.
5
One-Class OOP App See crawler.py, linked from web site.
Don't run it for more than a couple of hours; your ISP or Digital Ocean will eventually throttle your bandwidth Uses three libraries, not counting sys: urllib3 http client certifi supports ssl and works with urllib3 re provides regex functionality Documentation and examples are available online for all of these Here is some help on regexes with re:
6
A Multi-Class Application
bank_account.py: class BankAccount: def __init__(self, num): self._balance = 0 self._num = num def withdraw(self, amount): self._balance -= amount def deposit(self, amount): self._balance += amount def get_balance(self): return self._balance def get_num(self): return self._num
7
A Multi-Class Application
bank.py: from bank_account import BankAccount class Bank: def __init__(self): self._accounts = [] def add_account(self, num): self._accounts.append(BankAccount(num)) def find_account(self, num): curr = None for index in range (len(self._accounts)): if(self._accounts[index].get_num() == num): curr = index return curr def account_deposit(self, num, amount): curr = self.find_account(num) if curr != None: self._accounts[curr].deposit(amount) def account_withdrawal(self, num, amount): return self._accounts[curr].withdraw(amount) return None def account_get_balance(self, num): return self._accounts[curr].get_balance()
8
A Multi-Class Application
Put all three files in the same directory. To run this application from a Linux/Windows/OSX command line, type python3 bank_driver.py. Idle has a menu item to run scripts. bank_driver.py: import sys from bank import Bank def main(): b = Bank() b.add_account(1) print('$ {:.2f}'.format(b.account_get_balance(1))) b.account_deposit(1, ) b.account_withdrawal(1, 50.75) if __name__ == "__main__": sys.exit(main())
9
Where are the Getters and Setters?
Python does not have a way to create truly private variables. The leading underscore in a name is just a marker that the programmer did not intend other classes to directly access a value, and particularly to directly change it. If you use variables that you want to make freely available form outside the class, name the variables without the leading underscores and just access them directly, rather than with getter and setter functions.
10
__str__ __str__ is Python's equivalent of toString, somewhat like overloading << in C++ __str overloads the str() cast for the type version 1: class Widget: def __init__(self, characteristic_a, characteristic_b): self._characteristic_a = characteristic_a self._characteristic_b = characteristic_b >>> w1 = Widget(1,2) >>> w1 <widget.Widget object at 0x7f72a155ada0> version 2: def __str__(self): return 'Widget with characteristic a = ' + str(self._characteristic_a) + ' and characteristic b = ' +str(self._characteristic_b) <widget.Widget object at 0x7f687b9f11d0> >>> str(w1) 'Widget with characteristic a = 1 and characteristic b = 2'
11
__repr__ __repr__ is another method for representing an object as a string, but it is normally used for debugging rather than helping end-users. It should return a string containing the code necessary to recreate the object. version 5: class Widget: def __init__(self, characteristic_a, characteristic_b): self._characteristic_a = characteristic_a self._characteristic_b = characteristic_b def __eq__(self, other): if((self._characteristic_a == other._characteristic_a) and (self._characteristic_b == other._characteristic_b)): return True else: return False def __add__(self, other): return Widget(self._characteristic_a + other._characteristic_a, self._characteristic_b + other._characteristic_b) def __str__(self): return 'Widget with characteristic a = ' + str(self._characteristic_a) + ' and characteristic b = ' +str(self._characteristic_b) def __repr__(self): return 'Widget({0},{1})'.format(self._characteristic_a, self._characteristic_b) >>> from widget import Widget >>> w1 = Widget(1,2) >>> w1 Widget(1,2) >>> w2 = Widget(3,4) >>> w3 = w1 + w2 >>> w3 Widget(4,6)
12
Operator Overloading Note that operators like ==, <=, !=, + are equivalent to functions. For example, if x and y are values of some type: x == y is equivalent to calling a boolean function x.equals(y), which returns True if the two values are equal (according to whatever test for equality you code) and False if they are not equal. z = x + y is equivalent to calling a function that returns a value of the same type which represents the total of the two values, again according to whatever definition you code. In Python, we can overload many operators by overriding dunder methods.
13
Operator Overloading Without overloaded ==
>>> from widget import Widget >>> w1 = Widget(1,2) >>> w1 <widget.Widget object at 0x7f687b9f11d0> >>> str(w1) 'Widget with characteristic a = 1 and characteristic b = 2' >>> w2 = Widget(1,2) >>> w1 == w2 False version 3: class Widget: def __init__(self, characteristic_a, characteristic_b): self._characteristic_a = characteristic_a self._characteristic_b = characteristic_b def __eq__(self, other): if((self._characteristic_a == other._characteristic_a) and (self._characteristic_b == other._characteristic_b)): return True else: return False def __str__(self): return 'Widget with characteristic a = ' + str(self._characteristic_a) + ' and characteristic b = ' +str(self._characteristic_b) True >>> w3 = Widget(3,4) >>> w1 == w3
14
Operator Overloading Without overloaded + >>> w1+w2
Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'Widget' and 'Widget' version 4: class Widget: def __init__(self, characteristic_a, characteristic_b): self._characteristic_a = characteristic_a self._characteristic_b = characteristic_b def __eq__(self, other): if((self._characteristic_a == other._characteristic_a) and (self._characteristic_b == other._characteristic_b)): return True else: return False def __add__(self, other): return Widget(self._characteristic_a + other._characteristic_a, self._characteristic_b + other._characteristic_b) def __str__(self): return 'Widget with characteristic a = ' + str(self._characteristic_a) + ' and characteristic b = ' +str(self._characteristic_b) >>> from widget import Widget >>> w1 = Widget(1,2) >>> w2 = Widget(3,4) >>> w3 = w1 + w2 >>> print(w3) Widget with characteristic a = 4 and characteristic b = 6
15
Text File I/O Write to a text file: import sys def main():
my_file = open('test_file.txt', 'w') # open file for writing in text, not binary, mode text = input('what do you have to say? ') size = my_file.write(text + '\n') # returns number of characters written, including the literal print('wrote ' + str(size) + ' characters') my_file.close() if __name__ == "__main__": sys.exit(main()) 'a' instead of 'w' allows you to append to an existing file
16
Text File I/O Read from a text file, part 1:
my_file = open('test_file.txt', 'r') # open file for reading in text, not binary, mode text = my_file.read() print(text) my_file.close() If the file is reasonably large, use an iterator to read one line at a time instead of reading the whole file into memory at once: my_file = open('wordsEn.txt', 'r') for line in my_file: print(line)
17
Text File I/O $ cat widgets.csv 1,2 3,4 5,6 import sys
Use string.split() to parse data from a text file to construct objects: $ cat widgets.csv 1,2 3,4 5,6 import sys from widget import Widget def main(): widgets = [] my_file = open('widgets.csv', 'r') # open file for reading in text, not binary, mode for line in my_file: data = line.split(',') w = Widget(data[0], data[1]) widgets.append(w) for widget in widgets: print(widget) if __name__ == "__main__": sys.exit(main())
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.