Python static methods and class methods

Static Method and Class Method

1. Static method

  • Decorate with the decorator @static method. Static methods need neither pass class objects nor instance objects
  • Static methods can also be accessed through instance objects and class objects
class Dog:
    type = 'Dog'
    def __init__(self):
        name = None

    #Static method
    @staticmethod
    def introduce():#Static methods do not automatically pass instance objects and class objects
        print('Canidae mammals belonging to the order Carnivora')

dog = Dog()
Dog.introduce()
dog.introduce()

Canidae mammals belonging to the order Carnivora
Canidae mammals belonging to the order Carnivora

Static methods are functions in classes and do not require instances.

Static methods are mainly used to store logical code. Logically, they belong to classes, but they have nothing to do with classes themselves. That is to say, they do not involve attributes and method operations in classes.

Understandably, static methods are independent, simple functions that are managed only in the namespace of a class for easy maintenance and management.

Class method

  • Methods owned by class objects
  • The decorator @classmethod is needed to identify it as a class method.
  • For class methods, the first parameter must be a class object, usually cls as the first parameter
class Dog:
    __type = 'Dog'

    #Class method, decorated with class
    @classmethod
    def get_type(cls):
        return cls.__type
print(Dog.get_type())

Use scenarios:

  • Class methods are defined when class objects (such as access to private class attributes, etc.) need to be used in methods.
  • Class methods are generally used in conjunction with class attributes.

Be careful:

When an object method with the same name, a class method, and a static method are defined in a class, the calling method takes precedence over the last defined method.

class Dog:
    def demo_mtehod(self):
        print('Object method.')

    @classmethod
    def demo_method(cls):
        print('Class methods.')

    @staticmethod
    def demo_method(): #Finally, it is defined. Priority of execution on invocation
        print('Static method.')

dog = Dog()
Dog.demo_method()
dog.demo_method()

Static method.
Static method.

property

In Python, it mainly provides a convenient way to manipulate attributes.

If we need to design a bank account class now, it includes the name of the account holder and the balance. (If we don't consider the specific operation interface now.)

Simple implementation

class Account(object):
    def __init__(self,name,money):
        self.name = name
        self.money = money
        

Questions:

Insecurity (design is simple and convenient, all attributes can be accessed and modified externally, very insecure)

Improvement 1

Hide implementation details

For account information, the amount is not allowed to be modified directly by the user. If you change it, you can only go to the window.

How to implement the program?

When using objects, try not to let users directly manipulate the attributes in the objects, because direct manipulation will bring security risks.

At this point, consider private attributes

class Account(object):
    def __init__(self,name,money):
        self.name = name
        self.money = money

After code improvement, all attributes are designed as private attributes. When they are used externally, they do not know the internal attributes, can not modify the object directly, and hide the details of implementation.

But there is a new problem. What if you really need to modify these two attributes?

Improvement 2 provides an accurate access

class Account(object):
    def __init__(self,name,money):
        self.name = name
        self.__balance = money

    def get_name(self):
        return self.name
    def set_balance(self,money):
        self.__balance = money
    def get_balance(self):
        return self.__balance
    

After modification, when using the object of this class externally, if you want to use the attributes in the object, you can only operate through the set/get interface provided in the class, which improves the security of the program.

In this way, the program basically meets the design requirements, but can it be more perfect?

If in the process of using the object of this class, due to misoperation, abnormal data is introduced, resulting in abnormal data. How can this be avoided?

For example, negative numbers, strings, or other types of objects appear when setting the amount.

Improvement 3 Guarantees Data Validity

In the set_balance method, the incoming data is judged effectively, and if it is invalid, the user is prompted to have problems.

class Account(object):
    def __init__(self,name,money):
        self.name = name
        self.__balance = money

    def get_name(self):
        return self.name
    def set_balance(self,money):
        if isinstance(money,int):
            if money > 0:
                self.__balance = money
            else:
                raise ValueError('Input amount incorrect')
        else:
            raise ValueError('Input amount is not a number')

        self.__balance = money
    def get_balance(self):
        return self.__balance

After several versions of iteration, the program looks more robust and more secure.

But in the use process, it can be more refined.

Attribute operation

In the property class, a property class is provided. By setting up the object to create this class, when using the private property of the object, we can no longer use the method of calling the function of the property, but use the property just like the common property, so as to provide convenience for the developer.

property(fget = None,fset = None,fdel = None,doc = None)#property attribute

property is a class. The _init_ method consists of four parameters. After the instance, it returns an object to manipulate the properties.

  • Parametric 1: Attribute acquisition method
  • PARAMETER 2: THE SETTING METHOD OF ATTRIBUTES
  • Parametric 3: Method of deleting attributes
  • Parametric 4: Attribute description

(In order, or you will make a mistake)

class Account(object):
    def __init__(self,name,money):
        self.__name = name
        self.__balance = money

    def __get_name(self):
        return self.__name

    def set_balance(self,money):
        if isinstance(money,int):
            if money > 0:
                self.__balance = money
            else:
                raise ValueError('Input amount incorrect')
        else:
            raise ValueError('Input amount is not a number')


    def get_balance(self):
        return self.__balance
    #Use the property class to set traversal access to properties
    name = property (__get_name)
    balance = property(get_balance,set_balance)

ac = Account('Tom',10000)
print(ac.name)
print(ac.balance)
ac.balance = 1000
print(ac.balance)

Tom
10000
1000

class Account(object):
    def __init__(self, name, money):
        self.__name = name
        self.__balance = money

    @property
    def name(self):
        return self.__name

    @property
    def balance(self):
        return self.__balance

    @balance.setter
    def balance(self, money):
        if isinstance(money, int):
            if money > 0:
                self.__balance = money
            else:
                raise ValueError('Input amount incorrect')
        else:
            raise ValueError('Input amount is not a number')


ac = Account('Tom', 10000)
print(ac.name)
print(ac.balance)
ac.balance = 1000
print(ac.balance)

After using the property class instance object, when using the attributes in the object, it can be invoked as if using common public attributes, but the set/get method is actually invoked. In the case of an instance property object, not all parameters need to be written, for example, the name in the example provides only the get method and is a private method. This completely hides the internal implementation details.

self

What if the properties of an object need to be used in its methods?

  • Keyword self is mainly used in object method to represent the object calling the method.
  • Using self in the method, we can get the object that calls the current method, and then get the attributes and methods of the object.

When calling the method of an object, why don't you need to set the parameters corresponding to self?

  • When an object calls its method, the Python interpreter passes the object to the method as the first parameter, so the developer only needs to reserve the first parameter self when redefining it.
class Cat:
    #Method
    def introduce(self):
        print('name is %s,age is : %d'%(self.name,self.age))

#Instantiate, create an object
cat = Cat()
cat.name = 'aa'
cat.age = 8
cat.introduce()

name is aa,age is : 8

Define attributes within methods

  • Using self to manipulate attributes and variable names of objects is similar in effect.
class Cat:
    def introuce(self):
        self.type = 'Small animals'

cat = Cat()
cat.introuce()
print(cat.type)

_ new_ Method

  • When an object is created, the system automatically calls the _new_ method.
  • Developers can use the _new_ method to customize the object creation process.

-_ new_ must have at least one parameter cls representing the class to be instantiated, which is automatically provided by the Python interpreter when instantiated
-_ New_ must have a return value to return the instance instantiated. This is especially important when you implement _ new_ yourself. You can return instances from the parent class _ new_ or directly from the object __________ instance.
-_ init_ has a parameter self, which is the instance returned by _new_. On the basis of _new_, init_ can complete some other initialization actions, and _init_ does not need a return value.
- If a custom parameter is passed when an object is created and the new method is rewritten, the new method must also "reserve" the parameter, otherwise the _init_ method will not be able to obtain the parameter.

class A(object):
    def __new__(cls, x):
        print ('this is in A.__new__, and x is ', x)

        return super(A, cls).__new__(cls)

    def __init__(self, y):
        print ('this is in A.__init__, and y is ', y)

class C(object):
    def __new__(cls, n):
        print ('this is in C.__new__, and n is ', n)
        return super(C, cls).__new__(cls)

    def __init__(self, a):
        print ('this is in C.__init__, and a is ', a)


class B(A):
    def __new__(cls, z):
        print ('this is in B.__new__, and z is ', z)
        return A.__new__(cls, z)

    def __init__(self, m):
        print ('this is in B.__init__, and m is ', m)

# class B(A):
#     def __new__(cls, z):
#         print 'this is in B.__new__, and z is ', z
#         return object.__new__(cls)
#     def __init__(self, m):
#         print 'this is ni B.__init__, and m is ', m

if __name__ == '__main__':
    a = A(100)
    print ('=' * 20)
    b = B(200)
    print (type(b))

this is in A.new, and x is 100
this is in A.init, and y is 100

====================

this is in B.new, and z is 200
this is in A.new, and x is 200
this is in B.init, and m is 200
<class 'main.B'>

_ call__method

Objects are parenthesed to trigger execution

The execution of the constructor is triggered by the creation of an object, that is, object = class name ()

For example, the execution of the _call_ method is triggered by the parentheses of the object, that is, the object () or the class ().

class A(object):
    def __call__(self,x):
        print('call',x)
a = A()
a('123')

_ doc_ method

This property cannot be inherited to subclasses

class Foo:
    """This is a note."""
    pass
class Bar(Foo):
    pass
print(Foo.__doc__)
print(Bar.__doc__)

This is a note.

None

Keywords: Attribute Python

Added by juminoz on Thu, 01 Aug 2019 06:44:34 +0300