├── .gitignore ├── README.md ├── chapter_01 └── main.py ├── chapter_02 └── main.py ├── chapter_03 └── main.py ├── chapter_04 └── main.py ├── chapter_05 └── main.py ├── chapter_06 └── main.py ├── chapter_07 └── main.py ├── chapter_08 └── main.py ├── chapter_09 └── main.py ├── chapter_10 └── main.py ├── chapter_11 └── main.py ├── chapter_12 └── main.py ├── chapter_13 ├── __init__.py ├── action │ ├── __init__.py │ ├── action.py │ ├── create_student_action.py │ └── delete_student_action.py └── main.py ├── chapter_14 └── main.py ├── chapter_15 └── main.py ├── chapter_16 └── main.py ├── chapter_17 └── main.py ├── chapter_18 ├── __init__.py ├── main.py ├── required_string.py ├── student_1.py └── student_2.py ├── chapter_20 ├── __init__.py └── main.py └── chatper_19 └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | **/venv 2 | **/.idea 3 | **/target 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python_oop 2 | -------------------------------------------------------------------------------- /chapter_01/main.py: -------------------------------------------------------------------------------- 1 | class Student: 2 | pass 3 | 4 | 5 | class Person: 6 | pass 7 | 8 | 9 | def main(): 10 | print(type(Student)) 11 | print(type(Person)) 12 | print(isinstance(Student, type)) 13 | 14 | print(Student) 15 | 16 | student_1 = Student() 17 | print(isinstance(student_1, Person)) 18 | 19 | print(student_1) 20 | 21 | student_1 = Student() 22 | 23 | print(student_1) 24 | print(hex(id(student_1))) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /chapter_02/main.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | 3 | 4 | class Student: 5 | student_count = 8 6 | 7 | 8 | def main(): 9 | print(Student.__name__) 10 | 11 | print(Student.student_count) 12 | print(getattr(Student, "student_count")) 13 | # print(Student.unknown) 14 | print(getattr(Student, "unknown", "10")) 15 | 16 | Student.student_count = 89 17 | setattr(Student, "student_count", 100) 18 | print(Student.student_count) 19 | 20 | Student.newattribute = "hello" 21 | print(Student.newattribute) 22 | 23 | # del Student.newattribute 24 | delattr(Student, "newattribute") 25 | # print(Student.newattribute) 26 | 27 | s1 = Student() 28 | s2 = Student() 29 | Student.student_count = 4 30 | print(s1.student_count) 31 | print(s2.student_count) 32 | 33 | pprint(Student.__dict__) 34 | 35 | 36 | if __name__ == '__main__': 37 | main() 38 | -------------------------------------------------------------------------------- /chapter_03/main.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | 3 | 4 | class Student: 5 | def __init__(self, name: str): 6 | self.name = name 7 | 8 | def say_hello(self, msg: str): 9 | print(f"Hello {msg}, {self.name}") 10 | 11 | 12 | def main(): 13 | # 1. create a physical object 14 | # 2. call __init__() to initialize this object 15 | s1 = Student("Jack") 16 | s2 = Student("Tom") 17 | 18 | s1.say_hello("1111") 19 | s2.say_hello("2222") 20 | 21 | s1.gender = 'Male' 22 | print(s1.gender) 23 | print(s2.gender) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /chapter_04/main.py: -------------------------------------------------------------------------------- 1 | 2 | class Student: 3 | def __init__(self, name: str): 4 | self.__name = name 5 | 6 | def __say_hello(self, msg: str): 7 | print(f"Hello {msg}, {self.__name}") 8 | 9 | 10 | def main(): 11 | s1 = Student("Jack") 12 | print(s1._Student__name) # _classname__attribute 13 | 14 | s1._Student__say_hello("1111") 15 | 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /chapter_05/main.py: -------------------------------------------------------------------------------- 1 | 2 | class Student: 3 | school = "abc" 4 | 5 | @classmethod 6 | def hello(cls): 7 | print(f"hello {cls.school}") 8 | 9 | @staticmethod 10 | def out(): 11 | print(f"hello {Student.school}") 12 | 13 | @staticmethod 14 | def size(value: int) -> float: 15 | return value * 1.5 16 | 17 | def speak(self): 18 | n = 12 19 | # n = Student.size(n) 20 | n = self.size(n) 21 | print(n) 22 | 23 | 24 | def main(): 25 | Student.hello() 26 | print(Student.school) 27 | Student.out() 28 | 29 | Student().speak() 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /chapter_06/main.py: -------------------------------------------------------------------------------- 1 | class MyDate: 2 | def __init__(self, year, month, day): 3 | self.year = year 4 | self.month = month 5 | self.day = day 6 | 7 | def __str__(self): 8 | print("str is called") 9 | return f"{self.year}-{self.month}-{self.day}" 10 | 11 | def __repr__(self): 12 | print("repr is called") 13 | return f"MyDate:{self.year}-{self.month}-{self.day}" 14 | 15 | def __eq__(self, other): 16 | print("eq is called") 17 | if not isinstance(other, MyDate): 18 | return False 19 | 20 | return self.year == other.year \ 21 | and self.month == other.month \ 22 | and self.day == other.day 23 | 24 | def __hash__(self): 25 | print("hash is called") 26 | return hash(self.year + self.month * 101 + self.day * 101) 27 | 28 | def __bool__(self): 29 | print("bool is called") 30 | return self.year > 2021 31 | 32 | def __del__(self): 33 | print("del is called") 34 | 35 | 36 | def main(): 37 | my_date_1 = MyDate(2022, 11, 3) 38 | my_date_2 = MyDate(2022, 11, 3) 39 | my_date_5 = MyDate(2020, 1, 1) 40 | my_date_3 = my_date_1 41 | print(my_date_1) 42 | print(repr(my_date_1)) 43 | 44 | my_date_5 = None 45 | 46 | print(my_date_1 is my_date_3) 47 | print(my_date_1 == my_date_2) 48 | 49 | date_set = set() 50 | date_set.add(my_date_1) 51 | print(hash(my_date_1)) 52 | 53 | my_date_4 = MyDate(2020, 2, 1) 54 | print(bool(my_date_1)) 55 | print(bool(my_date_4)) 56 | 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /chapter_07/main.py: -------------------------------------------------------------------------------- 1 | class Student: 2 | def __init__(self, name: str, age: int): 3 | self.name = name 4 | self.__age = age 5 | 6 | def get_age(self): 7 | return self.__age 8 | 9 | def set_age(self, age: int): 10 | if age < 0 or age > 200: 11 | raise Exception(f"Age {age} is not valid") 12 | self.__age = age 13 | 14 | def __str__(self): 15 | return f"{self.name}, {self.__age}" 16 | 17 | age = property(fget=get_age, fset=set_age) 18 | 19 | 20 | def main(): 21 | student = Student("Jack", 18) 22 | student.age = 3 23 | print(student.age) 24 | student.set_age(3) 25 | print(student.get_age()) 26 | 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /chapter_08/main.py: -------------------------------------------------------------------------------- 1 | class Student: 2 | def __init__(self, name: str, age: int): 3 | self.name = name 4 | self.__age = age 5 | 6 | @property 7 | def age(self): 8 | return self.__age 9 | 10 | @age.setter 11 | def age(self, age: int): 12 | if age < 0 or age > 200: 13 | raise Exception(f"Age {age} is not valid") 14 | self.__age = age 15 | 16 | def __str__(self): 17 | return f"{self.name}, {self.__age}" 18 | 19 | 20 | def main(): 21 | student = Student("Jack", 18) 22 | student.age = -3 23 | print(student.age) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /chapter_09/main.py: -------------------------------------------------------------------------------- 1 | class Square: 2 | def __init__(self, width): 3 | self.__width = width 4 | self.__area = None 5 | 6 | @property 7 | def width(self): 8 | return self.__width 9 | 10 | @width.setter 11 | def width(self, width): 12 | self.__width = width 13 | self.__area = None 14 | 15 | @property 16 | def area(self): 17 | if self.__area is None: 18 | self.__area = self.__width * self.__width 19 | 20 | return self.__area 21 | 22 | 23 | def main(): 24 | square = Square(5) 25 | print(square.area) 26 | square.width = 6 27 | print(square.area) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /chapter_10/main.py: -------------------------------------------------------------------------------- 1 | class Square: 2 | def __init__(self, width): 3 | self.__width = width 4 | self.__area = None 5 | 6 | @property 7 | def width(self): 8 | return self.__width 9 | 10 | @width.setter 11 | def width(self, width): 12 | self.__width = width 13 | 14 | @property 15 | def area(self): 16 | if self.__area is None: 17 | self.__area = self.__width * self.__width 18 | 19 | return self.__area 20 | 21 | @area.deleter 22 | def area(self): 23 | self.__area = None 24 | 25 | 26 | def main(): 27 | square = Square(5) 28 | print(square.area) 29 | square.width = 6 30 | del square.area 31 | print(square.area) 32 | 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /chapter_11/main.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | def __init__(self): 3 | print("Person:init is called") 4 | self.name = "Jack" 5 | 6 | 7 | class Student(Person): 8 | def __init__(self): 9 | super().__init__() 10 | print("Student:init is called") 11 | self.school = "Abc" 12 | 13 | 14 | class Stone: 15 | pass 16 | 17 | 18 | def main(): 19 | student = Student() 20 | print(student.name) 21 | print(student.school) 22 | 23 | print(isinstance(student, Student)) 24 | print(isinstance(student, Person)) 25 | 26 | person = Person() 27 | print(isinstance(person, Student)) 28 | 29 | print(issubclass(Student, Person)) 30 | print(issubclass(Person, Student)) 31 | 32 | stone = Stone() 33 | print(issubclass(Stone, Student)) 34 | print(isinstance(stone, Person)) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /chapter_12/main.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | color = 1 3 | 4 | def __init__(self): 5 | self.name = "Jack" 6 | 7 | def say(self): 8 | print("Hello from person") 9 | 10 | def print_color(self): 11 | print(self.color) 12 | 13 | 14 | class Student(Person): 15 | color = 2 16 | 17 | def __init__(self): 18 | super().__init__() 19 | self.school = "Abc" 20 | 21 | def say(self): 22 | super().say() 23 | print("Hello from student") 24 | 25 | 26 | class Worker(Person): 27 | pass 28 | 29 | 30 | def render(person: Person): 31 | person.say() 32 | 33 | 34 | def main(): 35 | student = Student() 36 | student.say() 37 | 38 | person = Person() 39 | person.say() 40 | 41 | person = Student() 42 | person.say() 43 | 44 | render(student) 45 | render(Worker()) 46 | 47 | print(Student.color) 48 | student.print_color() 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /chapter_13/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevencn76/python_oop/d89ffd3a3a6ad72f452de45a45bea4f38b2f75fc/chapter_13/__init__.py -------------------------------------------------------------------------------- /chapter_13/action/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevencn76/python_oop/d89ffd3a3a6ad72f452de45a45bea4f38b2f75fc/chapter_13/action/__init__.py -------------------------------------------------------------------------------- /chapter_13/action/action.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class Action(ABC): 5 | 6 | @abstractmethod 7 | def execute(self): 8 | pass 9 | -------------------------------------------------------------------------------- /chapter_13/action/create_student_action.py: -------------------------------------------------------------------------------- 1 | from chapter_13.action.action import Action 2 | 3 | 4 | class CreateStudentAction(Action): 5 | def execute(self): 6 | print("Create a new student") 7 | -------------------------------------------------------------------------------- /chapter_13/action/delete_student_action.py: -------------------------------------------------------------------------------- 1 | from chapter_13.action.action import Action 2 | 3 | 4 | class DeleteStudentAction(Action): 5 | def execute(self): 6 | print("Delete a student") 7 | -------------------------------------------------------------------------------- /chapter_13/main.py: -------------------------------------------------------------------------------- 1 | from chapter_13.action.action import Action 2 | from chapter_13.action.create_student_action import CreateStudentAction 3 | from chapter_13.action.delete_student_action import DeleteStudentAction 4 | 5 | 6 | def execute_action(action: Action): 7 | action.execute() 8 | 9 | 10 | def main(): 11 | create_student_action = CreateStudentAction() 12 | delete_student_action = DeleteStudentAction() 13 | 14 | execute_action(create_student_action) 15 | # execute_action(delete_student_action) 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /chapter_14/main.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class Gender(Enum): 5 | MALE = 1 6 | FEMALE = 2 7 | 8 | 9 | class Student: 10 | def __init__(self, gender: Gender): 11 | self.gender = gender 12 | 13 | 14 | def main(): 15 | print(type(Gender.MALE)) 16 | print(Gender.MALE.name) 17 | print(Gender.MALE.value) 18 | 19 | student = Student(Gender.MALE) 20 | 21 | if student.gender == Gender.MALE: 22 | print("This student is a male") 23 | else: 24 | print("This student is a female") 25 | 26 | s_gender = "FEMALE" 27 | student.gender = Gender[s_gender] 28 | print(student.gender) 29 | 30 | i_gender = 2 31 | print(Gender(i_gender)) 32 | 33 | for gg in Gender: 34 | print(gg.name) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /chapter_15/main.py: -------------------------------------------------------------------------------- 1 | import enum 2 | from enum import Enum 3 | 4 | 5 | class Status(Enum): 6 | SUCCESS = 1 7 | OK = 1 8 | FAIL = 2 9 | WRONG = 2 10 | 11 | 12 | @enum.unique 13 | class Gender(Enum): 14 | MALE = 1 15 | FEMALE = 2 16 | 17 | 18 | def main(): 19 | for s in Status: 20 | print(s.name) 21 | 22 | print(Status.__members__) 23 | 24 | print(Status.SUCCESS == Status.OK) 25 | print(Status.SUCCESS is Status.OK) 26 | 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /chapter_16/main.py: -------------------------------------------------------------------------------- 1 | import enum 2 | from enum import Enum 3 | from functools import total_ordering 4 | 5 | 6 | @enum.unique 7 | class Gender(Enum): 8 | MALE = 1 9 | FEMALE = 2 10 | 11 | def __str__(self): 12 | return f"{self.name}({self.value})" 13 | 14 | def __eq__(self, other): 15 | if isinstance(other, int): 16 | return self.value == other 17 | 18 | if isinstance(other, str): 19 | return self.name == other.upper() 20 | 21 | if isinstance(other, Gender): 22 | return self is other 23 | 24 | return False 25 | 26 | 27 | @total_ordering 28 | class WorkFlowStatus(Enum): 29 | OPEN = 1 30 | IN_PROGRESS = 2 31 | REVIEW = 3 32 | COMPLETE = 4 33 | 34 | def __lt__(self, other): 35 | if isinstance(other, int): 36 | return self.value < other 37 | 38 | if isinstance(other, WorkFlowStatus): 39 | return self.value < other.value 40 | 41 | return False 42 | 43 | 44 | def main(): 45 | for g in Gender: 46 | print(g) 47 | 48 | print(Gender.MALE == 1) 49 | print(Gender.MALE == "FEMALE") 50 | 51 | print(WorkFlowStatus.IN_PROGRESS < 2) 52 | print(WorkFlowStatus.IN_PROGRESS < WorkFlowStatus.COMPLETE) 53 | 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /chapter_17/main.py: -------------------------------------------------------------------------------- 1 | class Parent1: 2 | def __init__(self): 3 | pass 4 | 5 | def render(self): 6 | print("parent 1") 7 | 8 | def hello(self): 9 | print("hello parent 1") 10 | 11 | 12 | class Parent2: 13 | def __init__(self): 14 | pass 15 | 16 | def render(self): 17 | print("parent 2") 18 | 19 | def hello(self): 20 | print("hello parent 2") 21 | 22 | 23 | class Child(Parent2, Parent1): 24 | def __init__(self): 25 | Parent1.__init__(self) 26 | 27 | def render(self): 28 | super().render() 29 | 30 | def hello(self): 31 | Parent1.hello(self) 32 | 33 | 34 | def main(): 35 | child = Child() 36 | child.render() 37 | child.hello() 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /chapter_18/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevencn76/python_oop/d89ffd3a3a6ad72f452de45a45bea4f38b2f75fc/chapter_18/__init__.py -------------------------------------------------------------------------------- /chapter_18/main.py: -------------------------------------------------------------------------------- 1 | from chapter_18.student_1 import Student1 2 | from chapter_18.student_2 import Student2 3 | 4 | 5 | def main(): 6 | student_1 = Student1("Jack", "Ma") 7 | # student_1.last_name = "" 8 | 9 | student_2 = Student2() 10 | student_2.first_name = "Jack" #first_name.__set__(student_2, "Jack") 11 | student_2.last_name = "Ma" 12 | 13 | student_3 = Student2() 14 | student_3.first_name = " Tom" 15 | student_3.last_name = "Li" 16 | 17 | print(student_2.first_name) 18 | print(student_3.first_name) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /chapter_18/required_string.py: -------------------------------------------------------------------------------- 1 | class RequiredString: 2 | def __init__(self, trim: bool): 3 | self.__trim = trim 4 | 5 | def __set_name__(self, owner, name): 6 | self.__property_name = name 7 | 8 | def __set__(self, instance, value): 9 | if not isinstance(value, str): 10 | raise Exception(f"{self.__property_name} is not a string") 11 | 12 | value = value.strip() 13 | if len(value) == 0: 14 | raise Exception(f"{self.__property_name} is empty") 15 | 16 | instance.__dict__[self.__property_name] = value 17 | 18 | def __get__(self, instance, owner): 19 | if self.__property_name in instance.__dict__: 20 | return instance.__dict__[self.__property_name] 21 | 22 | return None 23 | -------------------------------------------------------------------------------- /chapter_18/student_1.py: -------------------------------------------------------------------------------- 1 | class Student1: 2 | def __init__(self, first_name: str, last_name: str): 3 | self.first_name = first_name 4 | self.last_name = last_name 5 | 6 | @property 7 | def first_name(self): 8 | return self.__first_name 9 | 10 | @first_name.setter 11 | def first_name(self, first_name): 12 | if not isinstance(first_name, str): 13 | raise Exception("First name is not a string") 14 | 15 | if len(first_name) == 0: 16 | raise Exception("First name is empty") 17 | 18 | self.__first_name = first_name 19 | 20 | @property 21 | def last_name(self): 22 | return self.__last_name 23 | 24 | @last_name.setter 25 | def last_name(self, last_name): 26 | if not isinstance(last_name, str): 27 | raise Exception("Last name is not a string") 28 | 29 | if len(last_name) == 0: 30 | raise Exception("Last name is empty") 31 | 32 | self.__last_name = last_name 33 | -------------------------------------------------------------------------------- /chapter_18/student_2.py: -------------------------------------------------------------------------------- 1 | from chapter_18.required_string import RequiredString 2 | 3 | 4 | class Student2: 5 | first_name = RequiredString(True) 6 | last_name = RequiredString(True) 7 | password = RequiredString(False) 8 | -------------------------------------------------------------------------------- /chapter_20/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevencn76/python_oop/d89ffd3a3a6ad72f452de45a45bea4f38b2f75fc/chapter_20/__init__.py -------------------------------------------------------------------------------- /chapter_20/main.py: -------------------------------------------------------------------------------- 1 | class InvalidArgumentException(Exception): 2 | def __init__(self, *args): 3 | super().__init__(args) 4 | 5 | 6 | def add(n1, n2): 7 | if not isinstance(n1, int) or not isinstance(n2, int): 8 | raise InvalidArgumentException("Argument is not int") 9 | 10 | return n1 + n2 11 | 12 | 13 | def main(): 14 | try: 15 | num = 2 16 | s = 10 17 | res = num / s 18 | 19 | print(res) 20 | 21 | names = ("Jack", "Tom") 22 | print(names[0]) 23 | 24 | add("a", "b") 25 | except ZeroDivisionError: 26 | print("ZeroDivisionError") 27 | except InvalidArgumentException as iae: 28 | print(f"Argument is not valid: {iae}") 29 | except Exception as ex: 30 | print(f"Exception: {ex}") 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /chatper_19/main.py: -------------------------------------------------------------------------------- 1 | def execute(*args, **kwargs): 2 | print(args) 3 | print(kwargs) 4 | 5 | 6 | class SquareNumber(int): 7 | def __new__(cls, value: int): 8 | return super().__new__(cls, value ** 2) 9 | 10 | 11 | class Student: 12 | def __new__(cls, first_name, last_name): 13 | obj = super().__new__(cls) 14 | obj.first_name = first_name 15 | obj.last_name = last_name 16 | return obj 17 | 18 | 19 | def main(): 20 | execute("abc") 21 | execute("abc", "def") 22 | execute("abc", 12) 23 | execute("abc", 34, name="Tom", age=55) 24 | 25 | num = SquareNumber(2) 26 | print(num) 27 | print(type(num)) 28 | print(isinstance(num, int)) 29 | 30 | student = Student("Jack", "Ma") 31 | print(student.first_name) 32 | print(student.last_name) 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | --------------------------------------------------------------------------------