cookbook_ Classes and Objects

1 showing a modified example of a string

May be achieved by defining __str __ () and __repr __ () method

class Pair:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def __str__(self):
        return "(%s,%s)"%(self.x,self.y)

    def __repr__(self):
        return "Pair(%s,%s)"%(self.x,self.y)

p = Pair(2,5)
print(p)
print("p is {0!r}".format(p))

 

For __repr __ (), the standard method is to let him have a string of text to meet the eval (repr (x)) == x

__str __ () is generated for a meaningful text

 

2 custom string output format

 

We want to support the output format from the object defined by the format () function and the string method

To customize the output format of the string, you can be defined __format __ () method in class 

_formats = {
    "ymd":"{d.year}-{d.month}-{d.day}",
    "mdy":"{d.month}/{d.day}/{d.year}",
    "dmy":"{d.day}/{d.month}/{d.year}"
}

class Date:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

    def __format__(self,code):
        if code == "":
            code = "ymd"
        fmt = _formats[code]
        return fmt.format(d = self)

d = Date(2018,9,26)
print(format(d))
print(format(d,"dmy"))
print(format(d,"mdy"))

 

 

3 Let object supports the context management protocol

 

We want the object supports the context management protocol, which can be triggered by the with statement.

We wanted object supports context management protocol, the object to be achieved by The __enter __ () and The __exit __ () method to realize such type of network connection.

from socket import socket,AF_INET,SOCK_STREAM

class LazyConnection:
    
    def __init__(self,address,family = AF_INET, type = SOCK_STREAM):
        self.address = address
        self.family = family
        self.type = type
        self.sock = None

    def __enter__(self):
        if self.sock is not None:
            raise RuntimeError("Already connected")
        self.sock = socket(self.family,self.type)
        self.sock.connect(self.address)
        return self.sock

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.sock.close()
        self.sock = None

conn = LazyConnection("www.baidu.com")

with conn as s:
    s.send(b'hahhahah')

 

 

4 When you create a large number of examples of how to save memory

When our program needs to create a large number of instances (one million), which will take up a lot of memory.

For these classes # primarily as a simple data structure is generally increased __slot__ attribute class definition, in order to significantly reduce the use of memory.

class Date:
    __slots__ = ["year","month","day"]

    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

 

When defining the __slots__ property, python will use a more compact internal representation, property will be added to the instance of a small array, __dict__ no longer created for each instance.

Side effects we can not add a new property as an example. It is an optimization tool

 

5 Packaging category name

In python, to attribute a single leading underscore _ is considered a private property

class A:
    def __init__(self):
        self._name = "jiaojianglong"
        self.age = 24

    def _internal_method(self):
        print("i am a internal method")


a = A()
print(a._name) #jiaojianglong

 

 

python does not prevent access to property, but the compiler will not do prompt. If forced access would be considered rude.

In the class definition is also seen names beginning with a double underscore __, names beginning with a double underscore name will lead to restructuring of behavior emerge

class B:
    def __init__(self):
        self.__name = "jiaojianglong"

b = B()
# print(b.__name)#AttributeError: 'B' object has no attribute '__name'
print(b._B__name)#jiaojianglong

 

Such behavior is to inherit, to attribute the beginning of the double underscore are not covered by a quilt class and inheritance.

class C(B):
    def __init__(self):
        super().__init__()

c = C()
print(c._B__name)#jiaojianglong

 

 

In most cases we use a single underline, when it comes to the use of a subclass inherits problems covered by double underline

When we want to define a variable, but the name could conflict with the reserved fields, based on this, we add a single underline to show the difference after the name. lambda_

 

6 Create a manageable property

# Of instances in the acquisition and setting, we want to add some additional processing.

class Person:
    def __init__(self,first_name):
        self.first_name = first_name

    @property
    def first_name(self):
        return self._first_name

    @first_name.setter
    def first_name(self,value):
        if not isinstance(value,str):
            raise TypeError("Excepted a string")
        self._first_name = value



p = Person("jiao")
print(p.first_name)

 

When you create instances, __ inti __ () we will name assigned to self.first_name, actually calls the setter methods, so the name is actually stored in the self._first_name

 

7 call the parent class method

# We want to call a parent class method, this method in a subclass has been covered.

class A:
    def spam(self):
        print("A.spam")

class B(A):
    def spam(self):
        print("B.spam")
        super().spam()

b = B().spam()#B.spam,A.spam

print(B.__mro__)#(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

 

 

Contention for each class, python list will calculate a method called resolution order (MRO) are, MOR simply a list of all linearly arranged base class.

 

8 extended attribute in the subclass

We want to extend the functionality of a property in the subclass, and this property is defined in the parent class

 

9 creates a new form instance class attribute or attributes

If you want to define a new form instance attribute, the function may be defined as a descriptor.

class Integer():

    def __init__(self,name):
        self.name = name

    def __get__(self, instance, owner):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value,int):
            raise TypeError("Expected an int")
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        del instance.__dict__[self.name]


class Point:
    x = Integer("x")
    y = Integer("y")

    def __init__(self,x,y):
        self.x = x
        self.y = y

p = Point(2,3)
print(p.x)#2
p.y = 5
print(p.y)#5
# p.x = "a"#TypeError: Expected an int
print(Point.x)#<__main__.Integer object at 0x00000141E2ABB5F8>

 

the __get __ () method seem complicated because the difference between the instance variables and class variables, if the class variable is simply returns the descriptor itself, if it is returned instance variable defined value

 

About descriptors, often easily confused place is that they can only be defined at the level of the class, can not be generated according to an example, the following code will not work

class Point:

    def __init__(self,x,y):
        self.x = Integer("x")
        self.y = Integer("y")
        self.x = x
        self.y = y

p = Point(2,"c")
print(p.x)#2
print(p.y)#c

class Typed:
    def __init__(self,name,expected_type):
        self.name = name
        self.expected_type = expected_type


    def __get__(self, instance, owner):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value,self.expected_type):
            raise TypeError("Expected %s"%self.expected_type)
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        del instance.__dict__[self.name]

def typeassert(**kwargs):
    def decorate(cls):
        for name,expected_type in kwargs.items():
            setattr(cls,name,Typed(name,expected_type))
        return cls
    return decorate

@typeassert(name=str,shares = int,price=float)
class Stock:
    def __init__(self,name,shares,price):
        self.name = name
        self.shares = shares
        self.price = price

 

For small amounts of custom or the use of property simpler, if a large number of customized using the descriptor is simpler

Guess you like

Origin www.cnblogs.com/jiaojianglong/p/11260151.html