This is the 24th day of my participation in Gwen Challenge

We have arrived at the object oriented tutorial stage of Python ๐Ÿ˜„, which immediately comes to mind the three characteristics of object oriented. 1. Encapsulation 2. Inheritance 3. Polymorphism

Object Oriented Programming, OOP for short

The difference between object-oriented and procedural

The difference is that there is no Object, haha, Object oriented is through this Object to pass the message, for example, when writing code, Object oriented is the first to consider whether there is this Object, if there is no Object to create this Object. An object is an Instance of a Class, and in that Class there are properties specific to that Class, as well as behaviors (methods). Procedure oriented, without the concept of classes and objects, the code is all wrapped functions and variables.

For example, printing students’ grades for process oriented:

std1 = { 'name': 'Michael'.'score': 98 }
std2 = { 'name': 'Bob'.'score': 81 }
def print_score(std) :
    print('%s: %s' % (std['name'], std['score']))
Copy the code

Object-oriented:

class Student(object) :
    age=18 # class attribute
    def __init__(self, name, score) :
        self.name = name # instance attributes
        self.score = score # instance attributes

    def print_score(self) :
        print('%s: %s' % (self.name, self.score))

bart = Student('Bart Simpson'.59)
lisa = Student('Lisa Simpson'.87)
print(bart) # <__main__.Student object at 0x000001F7D6996DF0>
bart.print_score() # Bart Simpson: 59
lisa.print_score() # Lisa Simpson: 87
print(Student.age) # 18
print(bart.age)     # 18
Copy the code

From the object-oriented example above,

  1. Class Student(object): represents a class derived from the Class Object. The class name is usually capitalized, just like Java.

  2. Print (bart); print(bart); print(bart); print(bart); print(bart)

  3. Def __init__(self, name, score): method (note double underline)

    Note that the first argument to the __init__ method is always self, representing the created instance itself, so inside the __init__ method you can bind various properties to self, since self refers to the created instance itself

    There is the Feel of a Java constructor, except that the first argument to each method is self

  4. Instance properties: Bound by instance variables or self

  5. Class attribute: age=18 as above

Access restriction (encapsulation)

Private variables: special variables that start with a double underscore and cannot end with a double underscore (not directly accessible)

In some cases, you will see the instance variable names begin with an underscore, such as _name, such external instance variable is accessible, but, according to established rules, when you see such a variable, which means, “although I can be accessed, but, please put me as a private variable, don’t visit”. Is an instance variable starting with a double underscore necessarily inaccessible from the outside? Not really. __name cannot be accessed directly because the Python interpreter has changed the __name variable to _Student__name, so it is still possible to access __name via _Student__name:

Improve the robustness of the program by privatizing the variable and providing get/set methods to get/set the variable (after all, arguments can be handled in methods).

class Student(object) :
    
    def __init__(self, name, score) :
        self.__name = name
        self.__score = score

    def print_score(self) :
        print('%s: %s' % (self.__name, self.__score))

    def get_score(self) :
        return self.__score
    
    def set_score(self, score) :
        self.__score = score
        
bart = Student('Bart Simpson'.59)
print(bart.__name) # 'Student' object has no attribute '__name'
print(bart._Student__name) # Bart Simpson
bart.set_score(88)
print(bart.get_score()) # 88

Copy the code

inheritance

An inherited class is called a Base class, a parent class, or a superclass (Base class, Super class). Example: Parent class: Animal, subclass Dog

class Animal(object) :
    __age=1
    def run(self) :
        print('Animal is running... ')
    
    def set_age(self,age) :
        self.__age=age
    
    def get_age(self) :
        return self.__age


class Dog(Animal) :
    def run(self) :
        print('Dog is running... ')

class Cat(Animal) :
    def run(self) :
        print('Cat is running... ')

d=Dog()
d.run()
d.set_age(2)
print(d.get_age())
print(d.__age)

Copy the code

Well, this python is really neat to write! Just change the classes in parentheses.

Inheritance, like Java, has the public properties and methods of the parent class, after all, private ones are not accessible.

polymorphism

What is polymorphism? Polymorphism refers to the many forms of things. Animals can run, but cats and dogs run differently.

The forehead.. This Java has overloading and overwriting, corresponding to compile-time polymorphism and runtime polymorphism, respectively. But this Python is interpreted. This should just be run-time polymorphism.

Runtime polymorphism is the essence of object orientation.

The good thing about polymorphism is that when we need to introduce Dog, Cat, Tortoise… We only need to accept Animal types because Dog, Cat, Tortoise… They’re all Animal, and then I’m going to do it as Animal. Since the Animal type has a run() method, any type passed in as long as it is an Animal class or subclass will automatically call the run() method of the actual type

Consider this example: Define a function that accepts animal

def run_twice(animal) :
    animal.run()
    animal.run()

run_twice(Animal())
# Animal is running...
# Animal is running...

run_twice(Dog())
# Dog is running...
# Dog is running...
Copy the code

Runtime polymorphism has two characteristics:

  1. Methods to rewrite
  2. A superclass reference points to a subclass object

Static language VS dynamic language

For static languages (such as Java), if the Animal type is passed in, the object passed in must be Animal or a subclass of it; otherwise, the run() method cannot be called. For a dynamic language like Python, you don’t necessarily need to pass in the Animal type. We just need to ensure that the passed object has a run() method:

๐Ÿคจ

This is the “duck type” of dynamic languages, which does not require a strict inheritance system, as long as an object “looks like a duck and walks like a duck”, it can be considered a duck. Python’s “file-like object” is a duck type. For a real file object, it has a read() method that returns its contents. However, many objects that have a read() method are treated as “file-like objects”. Many functions take a “file-like object” argument, and you don’t have to pass in the actual file object. You can pass in any object that implements the read() method.

Note: The duck-type nature of dynamic languages makes inheritance less necessary than it is for static languages.

Obtaining Object Information

type()

Returns the corresponding Class type to determine whether an object is a function. You can use constants defined in the Types module

import types
print(type(123))  #<class 'int'>
print(type('hello world'))  #<class 'str'>
print(type(abs))  #<class 'builtin_function_or_method'>
def fn() :
    pass 
print(type(fn)) #<class 'function'>
print(types.BuiltinFunctionType) #<class 'builtin_function_or_method'>
print(types.FunctionType) #<class 'function'>
Copy the code

isinstance()

I’ve used this a lot before,

print(isinstance('hello'.str)) # True
# is not one of the types
print(isinstance('hello', (int.list.str))) # True
Copy the code

Isinstance () is always preferred to isinstance(). You can use a given type and its subclasses in a single row.

dir()

Gets all properties and methods of an object, which returns a list of strings

print(dir(str))'__add__'.'__class__'.'__contains__'.'__delattr__'.'__dir__'.'__doc__'.'__eq__'.'__format__'.'__ge__'.'__getattribute__'.'__getitem__'.'__getnewargs__'.'__gt__'.'__hash__'.'__init__'.'__init_subclass__'.'__iter__'.'__le__'.'__len__'.'__lt__'.'__mod__'.'__mul__'.'__ne__'.'__new__'.'__reduce__'.'__reduce_ex__'.'__repr__'.'__rmod__'.'__rmul__'.'__setattr__'.'__sizeof__'.'__str__'.'__subclasshook__'.'capitalize'.'casefold'.'center'.'count'.'encode'.'endswith'.'expandtabs'.'find'.'format'.'format_map'.'index'.'isalnum'.'isalpha'.'isascii'.'isdecimal'.'isdigit'.'isidentifier'.'islower'.'isnumeric'.'isprintable'.'isspace'.'istitle'.'isupper'.'join'.'ljust'.'lower'.'lstrip'.'maketrans'.'partition'.'replace'.'rfind'.'rindex'.'rjust'.'rpartition'.'rsplit'.'rstrip'.'split'.'splitlines'.'startswith'.'strip'.'swapcase'.'title'.'translate'.'upper'.'zfill']
Copy the code

Special variables like the __len__ method above return length. In Python, if you call len() to try to get the length of an object, in fact, inside len() it automatically calls the object’s __len__() method, so the following code is equivalent:

len('ABC') # 3
'ABC'.__len__() # 3

# override len method
class MyDog(object) :
    def __len__(self) :
        return 10
len(MyDog()) # 10

Copy the code

Getattr (), setattr(), and hasattr()

Direct manipulation of an object’s state: Note that we only retrieve object information if we don’t already know it.

len('ABC')
'ABC'.__len__()
class MyDog(object) :
    def __init__(self) :
        self.x=9
    def power(self) :
        return self.x**2
    def __len__(self) :
        return 10
d=MyDog()
print(len(d)) # 10
print(d.x) # 9
print(hasattr(d,'x')) # True
if(not hasattr(d,'y')) :setattr(d,'y'.100)
print('y is {}'.format(getattr(d,'y'))) # y is 100
An AttributeError error is raised when attempting to obtain an attribute that does not exist:
print('z is {}'.format(getattr(d,'z'))) # AttributeError: 'MyDog' object has no attribute 'z'

print('z is {}'.format(getattr(d,'z'.222))) Can be given a default value of 222, return if not present.
fn=getattr(d,'power') Get the function
print(d.power()) # 81
print(fn()) # 81

Copy the code

Proper use

Suppose we want to read an image from a file stream FP, we first determine whether the FP object has a read method. If so, the object is a stream, and if not, it cannot be read. Hasattr () comes in handy. Note that in a dynamic language like Python, the presence of a read() method does not mean that the FP object is a file stream, depending on the duck type. It may be a network stream or a byte stream in memory, but as long as the read() method returns valid image data, it does not affect the ability to read the image.

def readImage(fp) :
    if hasattr(fp, 'read') :return readData(fp)
    return None
Copy the code

The last

Welcome friends to discuss the question ~

If you think this article is good, please give it a thumbs-up ๐Ÿ˜

Let’s start this unexpected meeting! ~

Welcome to leave a message! Thanks for your support! ใƒพ(โ‰งโ–ฝโ‰ฆ*)o go!!

I’m 4ye. We should… next time. See you soon!! ๐Ÿ˜†