class
Class definition
class Person: def __init__(self, name, age): self.name = name self.age = age def myfunc(self): print("Hello my name is " + self.name) p1 = Person("Bill", 63) p1.myfunc()
attribute
Class properties
class Person: name = "person" def __init__(self, name, age): self.name = name self.age = age p1 = Person("Bill", 63) print(Person.name) print(p1.name)
result
person Bill
getattr/getattribute
class User: def __getattribute__(self, item): if (item == "age"): return 0 def __getattr__(self, item): if (item == "age"): return 99
Private property
class Person: def __init__(self, name, age): self.__name = name self.age = age def getName(self): return self.__name p1 = Person("Bill", 63) print(p1.age) print(p1.getName()) # Can be accessed by method print(p1._Person__name) # This way is still accessible print(p1.__name) # This way is inaccessible
Dynamic properties
class Person: def __init__(self, name, age): self.name = name self.age = age @property def sex(self): return "male" p1 = Person("Xiao Ming", 63) print(p1.name) print(p1.sex)
result
Xiao Ming male
It can be seen that
Dynamic properties, like the calculated properties of vue, can access methods like accessing properties.
Data descriptor / non data descriptor
import numbers # Data descriptor class IntField: def __get__(self, instance, owner): return self.value def __set__(self, instance, value): if not isinstance(value, numbers.Integral): raise ValueError("need int value") self.value = value def __delete__(self, instance): pass # Non data descriptor class NoDataField: def __get__(self, instance, owner): return 4 class User: age = IntField() if __name__ == "__main__": u = User() u.age = 10
In this way, if the assignment is not a number, an error will be reported
This allows you to limit the type of parameter.
Get order of properties
Two ways to get properties
u = User() u.age # Equivalent to getattr(u, "age")
Gets the priority order of the properties
- Calling class__ getattribute__
- Data descriptor defined in class or base class
- Property user. In the instance__ dict__ ["age"]
- Non data descriptor in class
- Property of user. Class or base class__ dict__ ["age"]
- Call in class__ getattr__ method
- Throw AttributeError
View the properties of an instance
class User: def __init__(self, name, age): self.__name = name self.age = age u = User("Xiao Ming", 16) print(u.__dict__) # View the properties of an instance print(dir(u)) # You can only see the name of the attribute, not the value, but all the attributes you can see print(User.__dict__) # View properties of a class print(dir(User)) # View properties of a class
result
{'_User__name': 'Xiao Ming', 'age': 16} ['_User__name', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age'] {'__module__': '__main__', '__init__': <function User.__init__ at 0x017BD100>, '__dict__': <attribute '__dict__' of 'User' objects>, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None} ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
Classes and objects
class User: def __new__(cls, *args, **kwargs): return super().__new__(cls, *args, **kwargs) def __init__(self, name, age): self.__name = name self.age = age u = User("Xiao Ming", 16) print(getattr(u, "age"))
be careful
__ new__ It is used to generate objects from classes, and to invoke them before creating objects. init__ Not called. __ init__ Is used to initialize properties for an object.
method
Example method
class Person: def __init__(self, name, age): self.name = name self.age = age def get_age(self): return self.age p1 = Person("Xiao Ming", 63) print(p1.get_age())
Static method
class Person: def __init__(self, name, age): self.__name = name self.age = age @staticmethod def getName(): return "123" print(Person.getName()) # Can be accessed by method p1 = Person("Bill", 63) print(p1.getName()) # Can be accessed by method
be careful
Static methods can be called with classes or examples.
Class method
class Person: def __init__(self, name, age): self.name = name self.age = age @classmethod def getPerson(cls, name, age): return cls(name, age) p1 = Person.getPerson("Xiao Ming", 63) print(p1.name)
be careful
The main advantage of class methods is that there is no need to write the class name when generating class instances, so that once the class name changes, there is no need to modify the code in the class methods.
Judged to be empty
if (p1 is None):
Determine whether it is an instance of a class
class Person: def __init__(self, name, age): self.name = name self.age = age p1 = Person("Xiao Ming", 63) print(isinstance(p1, Person))
Delete attribute or object
a = object() b = a del a print(b) print(a)
result
<object object at 0x017265B0> Traceback (most recent call last): File "main.py", line 5, in <module> print(a) NameError: name 'a' is not defined
We will find that after a is deleted, b is still not destroyed. This is because the counter is + 1 every time it is referenced. Only when the counter is 0 will it be destroyed.
inherit
class Student(Person):
Python classes can inherit more than one class
class C(A,B):
be careful
Try not to use multiple inheritance when developing
super
Basic use
class A: def __init__(self) -> None: print("A") class B(A): def __init__(self) -> None: super().__init__() print("B") if __name__ == "__main__": b = B()
result
A B
Sequence of calls
class A: def __init__(self) -> None: print("A") super().__init__() class B(A): def __init__(self) -> None: print("B") super().__init__() class C(A): def __init__(self) -> None: print("C") super().__init__() class D(B, C): def __init__(self) -> None: print("D") super().__init__() print(D.__mro__) d = D()
result
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) D B C A
It can be seen that
The calling sequence is called according to the MRO algorithm Use class__ mro__ You can view the call order Properties and methods are both rules
abstract class
import abc class A(metaclass=abc.ABCMeta): @abc.abstractmethod def say(self): pass class B(A): def __init__(self): pass def say(self): pass if __name__ == "__main__": b = B()
be careful
If B does not implement the abstract method of A, an error will be reported.
Dynamically create classes
def create_class01(ctype): if (ctype == "user"): class User: name = "Xiao Ming" def say(self): print(f"{self.name} say") return User def create_class02(ctype): def say(self): print(f"{self.name} say") if (ctype == "user"): User = type("User", (), {"name": "Xiao Ming", "say": say}) return User if __name__ == "__main__": User = create_class02("user") u = User() print(u.name) u.say()
result
Xiao Ming Xiao Ming say