[Introduction to Python3 Day 12] Chapter 6 Objects and Classes (6.3-6.15)

6.3 Inheritance

--Specify an existing class you want to use and create a new class that defines only the part you want to add or change. (Inheritance) --In the new class, define only the parts you want to add or change. Then this definition is actually used, and the behavior of the ** overwritten old class is not used. This is called ** override **. --The original class is called the parent, superclass, base class, and the new class is called child, subclass, derived class. --The child class specializes in the parent class.


>>> class car():
...     pass
... 
#Inheritance of parent class. Enter the parent class name in ().
>>> class yugo(car):
...     pass
... 
>>> give_me_a_car=car()
>>> give_me_a_yugo=yugo()
>>> class car():
...     def exclaim(self):
...         print("I am a car!")
... 
>>> class yugo(car):
...     pass
... 
>>> give_me_a_car=car()
>>> give_me_a_yugo=yugo()
>>> give_me_a_car.exclaim()
I am a car!
>>> give_me_a_yugo.exclaim()
I am a car!

Method override

--The new class inherits everything from the parent class.


#define car class
>>> class car():
...     def exclaim(self):
...         print("I am a car")
... 
#Define yugo class
>>> class yugo(car):
...     def exclaim(self):
...         print("I am a Yugo! Much like a Car,but more Yugo-ish")
... 
#Create object
>>> give_me_a_car=car()
>>> give_me_a_yugo=yugo()
#(object.Method)Call an instance with
>>> give_me_a_car.exclaim()
I am a car
>>> give_me_a_yugo.exclaim()
I am a Yugo! Much like a Car,but more Yugo-ish


>>> class Person():
...     def __init__(self,name):
...         self.name=name
... 
#It inherits the Person class and takes the same arguments as its parent, but overrides the name value stored in the object.
>>> class MDPerson(Person):
...     def __init__(self,name):
...         self.name="Docter"+name
... 
>>> class JDPerson(Person):
...     def __init__(self,name):
...         self.name=name+"Esquire"
... 
#Object creation
>>> person=Person("Fudd")
>>> docter=MDPerson("Fudd")
>>> lowyer=JDPerson("Fudd")
>>> print(person.name)
Fudd
>>> print(docter.name)
DocterFudd
>>> print(lowyer.name)
FuddEsquire

6.5 Addition of methods

--Child classes can add methods that were not in the parent class.


>>> class car():
...     def exclaim(self):
...         print("I am a car")
... 
>>> class yugo(car):
...     def exclaim(self):
...         print("I am a Yugo! Much like a Car,but more Yugo-ish")
#Needed only for child classes_a_push()Add method
...     def need_a_push(self):
...         print("A little help here?")
... 
>>> give_me_a_car=car()
>>> give_me_a_yugo=yugo()
>>> give_me_a_yugo.need_a_push()
A little help here?
#General-purpose Car objects cannot react.
>>> give_me_a_car.need_a_push()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'car' object has no attribute 'need_a_push'

6.6 Request for support from parents by super

--You can call the parent method from the child class.


#Parent class definition
>>> class Person():
...     def __init__(self,name):
...         self.name=name
... 

#Child class definition
#In child class__init__()To define is the parent class__init__()I'm trying to replace a method and the parent class version isn't called automatically. Therefore, in order to call the parent class field 0 John, it must be called explicitly.
#Note that we are adding an email argument

#super()Extracts the definition of the parent class Person.
>>> class EmailPerson(Person):
...     def __init__(self,name,email):
...         super().__init__(name)
...         self.email=email
... 
#Create an object of EmailPerson class
>>> bob=EmailPerson("Bob Frapples","[email protected]")
>>> bob.name
'Bob Frapples'
>>> bob.email
'[email protected]'

--Using super () to get Person to do the same job as just a Person object.

6.7 self defense


#Find the class (Car) of the car object.
#Car class exclaim()Pass the car object as a self argument to the method.

>>> car=car()
>>> car.exclaim()
I am a car

#You can get the same result as above by passing the car object directly to the Car class with the exclaim method.
>>> Car.exclaim(car)
I am a car

6.8 Acquisition and setting of attribute values by properties

--Some object-oriented languages support the private object attribute, which is not directly accessible from the outside. Setter and getter methods are required to be able to read and write the value of private attributes.

--I understood the getters and setters as follows. --Getter → What to get the value --Setter → What to use when assigning a value


#Hidden as an attribute_Define a Duck class that has only things with the value name
>>> class Duck():
...     def __init__(self,input_name):
...         self.hidden_name=input_name
...     def get_name(self):
...         print("inside the getter")
...         return self.hidden_name
...     def set_name(self,input_name):
...         print("inside the setter")
...         self.hidden_name=input_name
#Two methods are defined as setter and getter of property called name. This will actually get when you reference the name of the Duck object_name()The method will be called.
#You can use property to control what happens when an attribute is accessed.
...     name=property(get_name,set_name)
... 
>>> fowl=Duck("Howard")
>>> fowl.name
inside the getter
'Howard'
#Get directly_name()Can also be called
>>> fowl.get_name()
inside the getter
'Howard'
#Assigning a value to the name property sets_The name method is called.
>>> fowl.name="Duffy"
inside the setter
>>> fowl.name
inside the getter
'Duffy'
#Direct set_name()Can also be called
>>> fowl.set_name("Duffy")
inside the setter
>>> fowl.name
inside the getter
'Duffy'

--Properties can be defined in the decorator. -@property is a decorator before the getter method -@ Method name.setter is the decorator before the setter method -** Getter and setter method names must be the same **.


>>> class Duck():
...     def __init__(self,input_name):
...         self.hidden_name=input_name
#@By using property, it can be implemented without using attribute name, and it becomes possible to refer to the attribute.
...     @property
...     def name(self):
...         print("inside the getter")
...         return self.hidden_name
...     @name.setter
...     def name(self,input_name):
...         print("inside the setter")
...         self.hidden_name=input_name
... 
>>> fowl=Duck("Howard")
>>> fowl.name
inside the getter
'Howard'
>>> fowl.name="Donald"
inside the setter
>>> fowl.name
inside the getter
'Donald'

#The property can also refer to the calculated value.
>>> class Circle():
...     def __init__(self,radius):
...         self.radius=radius
...     @property
...     def diameter(self):
...         return 2 * self.radius
... 
>>> c=Circle(5)
>>> c.radius
5
>>> c.diameter
10
#radius attribute can be rewritten at any time
>>> c.radius=7
>>> c.diameter
14
#If you do not specify the property setter, you cannot rewrite the property value from the outside. (Convenient for read-only)
>>> c.diameter=20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

6.9 Name mangling for private attributes

--There is a naming method for attributes that should be hidden from outside the class definition. (Add two underscores (__) to the beginning of the attribute)


>>> class Duck():
...     def __init__(self,input_name):
...         self.__name=input_name
...     @property
...     def name(self):
...         print("inside the getter")
...         return self.__name
...     @name.setter
...     def name(self,input_name):
...         print("inside the setter")
...         self.__name=input_name
... 
>>> fowl=Duck("Howard")
>>> fowl.name
inside the getter
'Howard'
>>> fowl.name="Donald"
inside the setter
>>> fowl.name
inside the getter
'Donald'
#__Inaccessible to name attribute
>>> fowl.__name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Duck' object has no attribute '__name'
#Name mangling
>>> fowl._Duck__name
'Donald'

6.10 Method type

--Some data (attributes) and functions (methods) are part of the class itself, and other data and functions are part of the objects created from the class. --If the first argument of the ** method is self ** in the class definition, it is a ** instance method . When a method is called, Python gives the method an object. - Class methods ** affect the entire class. Changes made to the class affect all objects. If you include the ** @ classmethod ** decorator in the class definition, the next function will be a class method. The ** first argument of this method is the class itself . In Python tradition, this argument is called cls. - Static methods ** have no effect on classes or objects. ** @staticmethod ** Can be defined with a decorator. ** Do not take self or cls as the first argument. ** **


#self.count(This makes it an attribute of the object instance)Not A.count(Class attributes)Note that it refers to. kids()In the method cls.I used count, but A.It may be count.
>>> class A():
...     count=0
...     def __init__(self):
...         A.count+=1
...     def exclaim(self):
...         print("I am an A!")
...     @classmethod
...     def kids(cls):
...         print("A has",cls.count,"little objects.")
... 
>>> e=A()
>>> b=A()
>>> w=A()
>>> A.kids()
A has 3 little objects.

#Static method definition
>>> class CoyoteWeapon():
...     @staticmethod
...     def commercial():
...         print("This CoyoteWeapon has been brought to you by Acme")
... 
#It can be executed without creating an object from the class.
>>> CoyoteWeapon.commercial()
This CoyoteWeapon has been brought to you by Acme

6.11 Duck typing


>>> class Quote():
...     def __init__(self,person,words):
...         self.person=person
...         self.words=words
...     def who(self):
...         return self.person
...     def says(self):
...         return self.words + "."
... 
#Since the initialization method is the same as the parent class__init__()The method is not overridden.
>>> class QuestionQuote(Quote):
...     def says(self):
...         return self.words + "?"
... 
>>> class ExclamationQuote(Quote):
...     def says(self):
...         return self.words + "!"
... 
>>> hunter=Quote("E","I")
>>> print(hunter.who(),"says:",hunter.says())
E says: I.
>>> hunted1=QuestionQuote("E","I")
>>> print(hunted1.who(),"says:",hunted1.says())
E says: I?
>>> hunted2=ExclamationQuote("E","I")
>>> print(hunted2.who(),"says:",hunted2.says())
E says: I!
#Python is who(),says()Any object that has a method (without inheritance) can be treated as an object with a common interface.
>>> class BBrook():
...     def who(self):
...         return "Brook"
...     def says(self):
...         return "Babble"
... 
>>> brook=BBrook()
>>> def who_says(obj):
...     print(obj.who(),"says",obj.says())
... 
>>> who_says(hunter)
E says I.
>>> who_says(hunted1)
E says I?
>>> who_says(hunted2)
E says I!
>>> who_says(brook)
Brook says Babble

6.12 Special methods

--__init __ () initializes the newly created object from the class definition with the passed arguments.


>>> class Word():
...     def __init__(self,text):
...         self.text = text
...     def equals(self,word2):
...         return self.text.lower() == word2.text.lower()
... 
>>> first=Word("ha")
>>> second=Word("HA")
>>> third=Word("eh")
>>> first.equals(second)
True
>>> first.equals(third)
False

#equals()Method__eq__()Change to the special name.
>>> class Word():
...     def __init__(self,text):
...         self.text = text
...     def __eq__(self,word2):
...         return self.text.lower() == word2.text.lower()
... 
>>> first=Word("ha")
>>> second=Word("HA")
>>> third=Word("eh")
>>> first==second
True
>>> first==third
False
>>> first=Word("ha")
>>> first
<__main__.Word object at 0x10ddeec50>
>>> print(first)
<__main__.Word object at 0x10ddeec50>
#In the Word class__str__()Or__repr__()Add methods to make the display easier to see.
>>> class Word():
...     def __init__(self,text):
...         self.text = text
...     def __eq__(self,word2):
...         return self.text.lower() == word2.text.lower()
...     def __str__(self):
...         return self.text
...     def __repr__(self):
...         return "Word(" + self.text + ")"
... 
>>> first=Word("ha")
#__repr__()use
>>> first
Word(ha)
#__str__()use
>>> print(first)
ha

--Special method for comparison

Method meaning
_qe_(x,y) x == y
_ne_(x,y) x != y
_lt_(x,y) x < y
_gt_(x,y) x > y
_le_(x,y) x <= y
_ge_(x,y) x >= y

--Special methods for arithmetic calculations

Method meaning
_add_(x,y) x + y
_sub_(x,y) x - y
_mul_(x,y) x * y
_floordiv_(x,y) x // y
_truediv_(x,y) x / y
_mod_(x,y) x % y
_pow_(x,y) x ** y

--Other special methods --The interactive interpreter uses the repr () function to echo out variables. --If you forget to define str () or repr (), the default string version of the object defined by Python will be used.

Method meaning
_str_(x) str(x)
_repr_(x) repr(x)
_len_(x) len(x)

6.13 Composition

--In some cases, composition and aggregation make more sense than inheritance.


#bill(Beak)、tail(tail)Create an object and give it to the new Duck class.
>>> class Bill():
...     def __init__(self,description):
...         self.description=description
... 
>>> class Taill():
...     def __init__(self,length):
...         self.length=length
... 
>>> class Duck():
...     def __init__(self,bill,tail):
...         self.bill=bill
...         self.tail=tail
...     def about(self):
...         print("This duck has a",self.bill.description,"bill and a",self.tail.length,"tail")
... 
>>> tail=Taill("long")
>>> bill=Bill("wide orange")
>>> duck=Duck(bill,tail)
>>> duck.about()
This duck has a wide orange bill and a long tail

6.14 When should I use classes and objects instead of modules?

--Classes support inheritance, but modules do not. --Objects are most useful when you need multiple instances with the same behavior (methods) but different internal states (attributes). ――When you need only one thing, a module is good. No matter how many times a Python module is referenced by a program, only one copy will be loaded. --When you have a variable with multiple values and you can pass them as arguments to multiple functions, it may be better to define it as a class.

6.14.1 Named tuples

--Named tuples are subclasses of tuples that allow you to access values not only by position ([offset]) but also by name (.name).

--Pass two arguments to the namedtuple function.

--Named tuples are not a data structure that Python automatically supplies, so you have to download the module to use them. --Advantages of named tuples --Behavior like an immutable object --Spatial and temporally more efficient than objects, --You can access attributes in dot notation instead of dictionary-style square brackets. --Can be used as a dictionary key.


>>> from collections import namedtuple
>>> Duck=namedtuple("Duck","bill tail")
>>> duck=Duck("wide orange","long")
#Create named tuples
>>> duck
Duck(bill='wide orange', tail='long')
#(.name)You can access the value with.
>>> duck.bill
'wide orange'
>>> duck.tail
'long'

#Named tuples can also be created from a dictionary.
>>> parts={"bill":"Wide orange","tail":"long"}
#Duck by extracting the keys and values of the parts dictionary by dictionaryizing the keyword arguments()Pass as an argument to.
>>> duck2=Duck(**parts)
>>> duck2
Duck(bill='Wide orange', tail='long')

#Named tuples are immutable, but they can return another named tuple with one or more field exchanges.
>>> duck3=duck2._replace(tail="M",bill="X")
>>> duck3
Duck(bill='X', tail='M')

#duck can also be defined as a dictionary.
>>> duck_dict={"bill":"A","tail":"I"}
>>> duck_dict
{'bill': 'A', 'tail': 'I'}
#You can add fields to the dictionary.
>>> duck_dict["color"]="green"
>>> duck_dict
{'bill': 'A', 'tail': 'I', 'color': 'green'}
#Cannot be added to named tuples.
>>> duck_dict.color="green"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'color'

6.15 Review assignment

6-1 Create an empty class called Thing and display it. Next, let's create an object called example from this class and display it as well. Are the displayed values the same or different?


>>> class Thing():
...     pass
... 
>>> example=Thing()
>>> print(Thing)
<class '__main__.Thing'>
>>> print(example)
<__main__.Thing object at 0x10de692d0>

6-2 Create a new object called Thing2 and assign the value "abc" to the class attribute called letters to display letters.


>>> class Thing2():
...     letters="abc"
... 
>>> print(Thing2.letters)
abc

6-3 Let's make another class. The name is Thing3. Now let's display letters by assigning "xyz" to the instance (object) attribute called letters.


>>> class Thing3():
...     def __init__(self):
...         self.letters="xyz"
... 
>>> something=Thing3()
>>> print(something.letters)
xyz

6-4 Create a class called Element with instance attributes of name, symbol, number, and create an object of this class with the values "Hydogen", "H", "1".


>>> class Element():
...     def __init__(self,name,symbol,number):
...         self.name=name
...         self.symbol=symbol
...         self.number=number
... 
>>> H=Element("Hydogen","H","1")

6-5 Create a dictionary with key / value pairs "name": "Hydrogen", "symbol": "H", "number": "1". Next, let's use this dictionary to create a hydrogen object of the Element class.


>>> dictionary={"name":"Hydrogen","symbol":"H","number":"1"}
>>> hydrogen=Element(dictionary["name"],dictionary["symbol"],dictionary["number"])
>>> hydrogen.name
'Hydrogen'
>>> hydrogen.symbol
'H'
>>> hydrogen.number
'1'

#The key name of the dictionary is__init()__Since it matches the argument of, the object can be initialized directly from the dictionary.
>>> hydrogen=Element(**dictionary)
>>> hydrogen.name
'Hydrogen'
>>> hydrogen.symbol
'H'
>>> hydrogen.number
'1'

6-6 For the Element class, let's define a method called dump () that displays the values of object attributes (name, symbol, number). Let's create a hydrogen object from this new definition and use dump () to display the attributes.


>>> class Element():
...     def __init__(self,name,symbol,number):
...         self.name=name
...         self.symbol=symbol
...         self.number=number
...     def dump(self):
...         print("name=%s,symbol=%s,number=%s"%(self.name,self.symbol,self.number))
... 
>>> hydrogen=Element("A","B","C")
>>> hydrogen.dump()
name=A,symbol=B,number=C

6-7 Let's call print (hydrogen). Next, change the method name dump to str in the Element definition, create a hydrogen object under the new definition, and call print (hydrogen) again.


>>> print(hydrogen)
<__main__.Element object at 0x10de9e510>
>>> class Element():
...     def __init__(self,name,symbol,number):
...         self.name=name
...         self.symbol=symbol
...         self.number=number
...     def __str__(self):
...         return ("name=%s,symbol=%s,number=%s"%(self.name,self.symbol,self.number))
... 
>>> hydrogen=Element("A","B","C")
#The print function of the object__str__()Call the method to get the string representation. Without this<__main__.Element object at 0x10de9e510>Returns a string like.
>>> print(hydrogen)
name=A,symbol=B,number=C

6-8 Let's rewrite Element and make name, symbol, number attributes private. And let's define a getter that returns a value for each.


>>> class Element():
...     def __init__(self,name,symbol,number):
...         self.__number=number
...         self.__symbol=symbol
...         self.__name=name
...     @property
...     def name(self):
...         return self.__name
...     @property
...     def symbol(self):
...         return self.__symbol
...     @property
...     def number(self):
...         return self.__number
... 
>>> hydrogen=Element("A","B","C")
>>> hydrogen.name
'A'
>>> hydrogen.symbol
'B'
>>> hydrogen.number
'C'


6-9 Let's define three classes, Bear, Rabbit and Octothorpe, define the only method, eats ().


>>> class Bear():
...     def eats(self):
...         return "berries"
... 
>>> class Rabbit():
...     def eats(self):
...         return "clover"
... 
>>> class Octothorse():
...     def eats(self):
...         return "campers"
... 
#Object creation is called like a function
>>> a=Bear()
>>> b=Rabbit()
>>> c=Octothorse()
>>> print(a.eats())
berries
>>> print(b.eats())
clover
>>> print(c.eats())
campers

6-10 Let's define Laser, Claw, SmartPhone classes. The three classes have does () as the only method.


>>> class Laser():
...     def does(self):
...         return "disintegrate"
... 
>>> class Claw():
...     def does(self):
...         return "crush"
... 
>>> class SmartPhone():
...     def does(self):
...         return "ring"
... 
#Composition
>>> class Robot():
...     def __init__(self):
...         self.laser=Laser()
...         self.claw=Claw()
...         self.smartphone=SmartPhone()
...     def does(self):
...         return """I have many attachments:
... My laser,to %s.
... My claw,to %s.
... My smartphone,to %s.""" %(
...     self.laser.does(),
...     self.claw.does(),
...     self.smartphone.does())
... 
>>> ro=Robot()
>>> print(ro.does())
I have many attachments:
My laser,to disintegrate.
My claw,to crush.
My smartphone,to ring.
>>> 

Impressions

I couldn't understand the setters and getters from the books alone, but I could find out and understand them. I felt that classes and objects were important units, so I took a lot of time to understand them.

Let's do our best again from tomorrow.

References

"Introduction to Python3 by Bill Lubanovic (published by O'Reilly Japan)"

Recommended Posts

[Introduction to Python3 Day 12] Chapter 6 Objects and Classes (6.3-6.15)
[Introduction to Python3 Day 11] Chapter 6 Objects and Classes (6.1-6.2)
[Introduction to Python3 Day 22] Chapter 11 Concurrency and Networking (11.1 to 11.3)
[Introduction to Python3 Day 1] Programming and Python
[Introduction to Python3 Day 13] Chapter 7 Strings (7.1-7.1.1.1)
[Introduction to Python3 Day 14] Chapter 7 Strings (7.1.1.1 to 7.1.1.4)
[Introduction to Python3 Day 15] Chapter 7 Strings (7.1.2-7.1.2.2)
[Introduction to Python3 Day 21] Chapter 10 System (10.1 to 10.5)
[Introduction to Python3, Day 17] Chapter 8 Data Destinations (8.1-8.2.5)
[Introduction to Python3, Day 17] Chapter 8 Data Destinations (8.3-8.3.6.1)
[Introduction to Python3 Day 19] Chapter 8 Data Destinations (8.4-8.5)
[Introduction to Python3 Day 18] Chapter 8 Data Destinations (8.3.6.2 to 8.3.6.3)
[Introduction to Python3 Day 23] Chapter 12 Become a Paisonista (12.1 to 12.6)
[Introduction to Python3 Day 20] Chapter 9 Unraveling the Web (9.1-9.4)
About python objects and classes
[Introduction to Python3 Day 8] Chapter 4 Py Skin: Code Structure (4.1-4.13)
[Introduction to Python3 Day 3] Chapter 2 Py components: Numbers, strings, variables (2.2-2.3.6)
[Introduction to Data Scientists] Basics of Python ♬ Functions and classes
[Introduction to Python3 Day 2] Chapter 2 Py Components: Numbers, Strings, Variables (2.1)
[Introduction to Python3 Day 4] Chapter 2 Py Components: Numbers, Strings, Variables (2.3.7-2.4)
Bind methods to Python classes and instances
Introduction to Effectiveness Verification Chapter 1 in Python
[Introduction to Python3 Day 7] Chapter 3 Py Tools: Lists, Tuples, Dictionaries, Sets (3.3-3.8)
[Introduction to Python3 Day 5] Chapter 3 Py Tools: Lists, Tuples, Dictionaries, Sets (3.1-3.2.6)
[Introduction to Python3 Day 10] Chapter 5 Py's Cosmetic Box: Modules, Packages, Programs (5.4-5.7)
[Introduction to Python3 Day 9] Chapter 5 Py's Cosmetic Box: Modules, Packages, Programs (5.1-5.4)
[Introduction to Python3 Day 6] Chapter 3 Py tool lists, tuples, dictionaries, sets (3.2.7-3.2.19)
Introduction to effectiveness verification Chapter 3 written in Python
Introduction to Python language
Introduction to OpenCV (python)-(2)
[Introduction to Udemy Python3 + Application] 64. Namespace and Scope
[Python for Hikari] Chapter 09-02 Classes (Creating and instantiating classes)
[Python for Hikari] Chapter 09-01 Classes (Basics of Objects)
Introduction to Effectiveness Verification Chapter 2 Written in Python
[Introduction to Udemy Python3 + Application] 35. Comparison operators and logical operators
The simplest Python memo in Japan (classes and objects)
[Chapter 5] Introduction to Python with 100 knocks of language processing
[Chapter 3] Introduction to Python with 100 knocks of language processing
[Chapter 2] Introduction to Python with 100 knocks of language processing
[Introduction to Udemy Python3 + Application] 68. Import statement and AS
[Technical book] Introduction to data analysis using Python -1 Chapter Introduction-
[Chapter 4] Introduction to Python with 100 knocks of language processing
Introduction to Python Django (2) Win
About Python variables and objects
Introduction to serial communication [Python]
[Introduction to Python] <list> [edit: 2020/02/22]
Introduction to Python (Python version APG4b)
An introduction to Python Programming
Introduction to Python For, While
[Introduction to Udemy Python3 + Application] 42. for statement, break statement, and continue statement
[Introduction to Udemy Python3 + Application] 39. while statement, continue statement and break statement
[Introduction to Udemy Python 3 + Application] 36. How to use In and Not
[Introduction to Udemy Python3 + Application] 50. Positional arguments, keyword arguments, and default arguments
Introduction to Effectiveness Verification Chapters 4 and 5 are written in Python
[Introduction to Python] Combine Nikkei 225 and NY Dow csv data
[Introduction to Udemy Python 3 + Application] 58. Lambda
[Introduction to Udemy Python 3 + Application] 31. Comments
perl objects and python class part 2.
Python ABC-Abstract Classes and Duck Typing
Introduction to Python Numerical Library NumPy
Practice! !! Introduction to Python (Type Hints)