This is the fourth day of my participation in Gwen Challenge

Wechat public number search [program yuan xiaozhuang], pay attention to the halfway program yuan how to rely on Python development to support the family ~

preface

An object instantiated by a class can call a function defined in the class directly, and can take the object itself as its first argument. Can a class also use a function in the class body like an object without passing the first argument? If we use a class that someone else has wrapped up, how do we determine if that class or object has a property? This article will take your friends to find out!

Bound and unbound methods

The first thing to be clear is that the functions defined in a class are called methods, which are a little different from ordinary functions. The functions defined in a class fall into two main categories: bound methods and unbound methods.

Binding approach

The special feature of the binding method is that the caller itself is automatically passed in as the first parameter. The binding method is divided into the method bound to the class and the method bound to the object instantiated by the class. The method caller bound to the object is the object, and the parameter automatically passed in is the object. A method bound to a class is called by the class and automatically passed in by the class.

A function defined normally in a class is bound to an object by default. A function defined in a class is bound to a class by adding the decorator @classMethod.

Class methods are automatically passed the class as the first argument when called by the class. Class methods are usually used to provide additional initialization instances in addition to __init__. It is important to note that class methods are specifically used by classes, and it makes no sense to call class methods on objects instantiated by classes.

class Animal() :
    
    def __init__(self, color) :
        self.color = color
    
    @classmethod
    def create_new_animal(cls) : 
        print('Create a new animal species')
        
>>> Animal.create_new_animal
<bound method Animal.create_new_animal of <class '__main__.Animal'> > > > >Animal.create_new_animal() # the class calls the class method and passes the class itself as the first argument to create a new animalCopy the code

Unbound method

When you add @staticmethod to a function defined in the class body, that method becomes an unbound method, also known as a staticmethod. Functions decorated with this decorator become normal functions that are not bound to any object and do not have the effect of automatic parameter passing.

class Animal() :
    
    def __init__(self, color) :
        self.color = color
    
    @staticmethod
    def create_new_animal() :   Static methods do not automatically pass parameters. They are normal functions
        print('Create a new animal species')
        
>>> Animal.create_new_animal
<function Animal.create_new_animal at 0x000001DAE53CE670>

>>> Animal.create_new_animal() creates a new Animal species>>> Animal('white'Create_new_animal () creates a new animal speciesCopy the code

reflection

Reflection refers to the dynamic acquisition of object attribute information in the process of program running. In the process of program running, if you want to obtain an object with unknown attributes, you can use reflection to analyze the object attributes. __dict__ is a built-in way to view the properties of an object, but it is not recommended to operate directly on the object.

Implementing reflection in Python is very simple. If you want to get the attributes of an object with unknown attributes, you can use the built-in Python interpreter function dir to get the list of attributes of any object. The elements in the list are strings.

>>> class Test() :
.    test = 'test'
.    def foo(self) :
.        print('test foo')...>>> dir(Test)
[..., 'foo'.'test']

>>> dir(Test())
[..., 'foo'.'test']
Copy the code

Hasattr setattr getattr delattr is the built-in function of the Python interpreter to manipulate the properties of the object.

t = Test()

# hasattr(obj, 'attribute name ') : Determines whether an object has an attribute
>>> hasattr(t, 'test')
True
>>> hasattr(t, 'test1')
False

# setattr(obj, 'attribute name ',' new attribute value ') : Modify a value of an object, add an attribute to the object if the attribute name does not exist
>>> setattr(t, 'test'.'test1')
>>> setattr(t, 'test1'.'test1')
>>> t.test
'test1'
>>> t.test1
'test1'

# getattr(obj, 'property name ') # get the property value of the object
>>> getattr(t, 'foo')
<bound method Test.foo of <__main__.Test object at 0x000001DAE4F9BF40>>
>>> getattr(t, 'test')
'test1'
>>> getattr(t, 'test1')
'test1'

# delattr(obj, 'property name ') # Delete the property of the object
>>> delattr(t, 'test1')
>>> hasattr(t, 'test1')
False
Copy the code

Reflection can be used to manipulate object properties flexibly through strings. The principle of reflection is based on object.__dict__.

# 1 Call dir function to check which properties can be
print(dir(obj))
# 2 Reflects the real property through the string to get the property value
print(obj.__dict__[dir(obj)[-2]])
Copy the code

Built-in methods

Python’s Class mechanism has a number of special built-in methods to help users highly customize their classes. These built-in methods start and end with double underscores and are automatically triggered when certain conditions are met. Let’s use __str__ and __del__ as examples to illustrate their use.

__str__ is automatically triggered when an object is printed, and the return value (which must be a string) is output as the result of the print. If __str__ does not exist in a custom class, the output of the printed object is the memory address of the object. When __str__ is present in a custom class, the print object output is the return value of the __str__ method.

The # class has no __str__ method
class Test:

    def test(self) :
        print('test')


t = Test()
print(t)  # <__main__.Test object at 0x000001F9EE618FD0>


The # class has __str__
class Test:

    def test(self) :
        print('test')

    def __str__(self) :
        return 'the Test object'
    
t = Test()
print(t)  # Test object

Copy the code

The __del__ method is triggered automatically when an object is deleted. Since Python’s garbage collection mechanism automatically cleans up unused resources in the program, there is no need to define a __del__ method if an object is only using application resources, but if it is designed to use system resources, such as open file objects, When Python’s garbage collection mechanism is not useful because of the operating system resources involved, you need to create a __del__ method for an object that automatically triggers the recycling of operating system resources when the object is deleted.

class Test:
    def __init__(self) :
        self.x = open('a.txt',mode='w')
        # self.x = occupies operating system resources

    def __del__(self) :
        print('run')
        Make a system call that tells the operating system to reclaim related system resources
        self.x.close()

obj = T()
del obj # obj.__del__()
Copy the code