__str__ and __repr__
If you want to turn an instance of a class into str, you need to implement a special method __str__ ():
class Person (object): __init__(self, Name, gender): self.name = name Self.gender = Gender def __str__(self): return ' (Person:%s,%s) '% (Self.name, self.gender)
Now try print on the interactive command line:
>>> p = person (' Bob ', ' Male ') >>> print P (person:bob, male)
However, if you hit the variable pdirectly:
>>> P<main. Person object at 0x10c941890>
It seems that __str__ () will not be called.
Because Python defines __str__ () and __repr__ ( ) Two methods,__str__ () is used to display to the user, and __repr__ () Used to be displayed to developers.
There's a lazy way to define __repr__ :
class Person (object): def __init__ (self, Name, gender): self.name = name Self.gender = Gender def _ _str__ (self): return ' (Person:%s,%s) '% (Self.name, self.gender) __repr__ = __str__
Task
Please define the __str__ and __repr__ methods for the Student class so that you can print out <student:name, gender, Score>:
Class Student: def __init__ (self, name, gender, score): super (Student, self). __INIT__ (name, gender) Self.score = Score
__cmp__
When sorting built-in data types such as int,str , Python's sorted () is sorted by the default comparison function cmp , but if a set of Student class, you must provide our own special method __cmp__ ():
Class Student (object): def __init__ (self, Name, score): self.name = name Self.score = score def __ Str__ (self): return ' (%s:%s) '% (Self.name, self.score) __repr__ = __str__ def __cmp__ (self, s): If Self.name < s.name: return-1 elif self.name > S.name: return 1 else: return 0
The Student class implements the __cmp__ () method, and__cmp__ compares it with the instance self and the incoming instance s , and returns 1 if it should be in front, if s should be in front, return 1 if both are equal, return 0.
The student class implements sorting by name:
>>> L = [Student (' Tim '), Student (' Bob ', Student),]>>> print sorted (L) [(alice:77), ( bob:88), (tim:99)]
Note : If the list contains more than just the Student class, __cmp__ may get an error:
L = [Student (' Tim '), Student (' Bob ', N), +, ' Hello ']print sorted (L)
Please think about how to solve.
Task
Please modify the Student __cmp__ method so that it sorts by the score from high to the bottom, the same score by name.
__len__
If a class behaves like a list, the len () function is needed to get the number of elements.
For the len () function to work properly, the class must provide a special method, __len__ (), which returns the number of elements.
For example, we write a Students class that passes the name in:
Class Students (object): def __init__ (self, *args): self.names = args def __len__ (self): return Len ( Self.names)
As long as the __len__ () method is implemented correctly, the len () function can be used to return the "length" of the Students instance:
>>> ss = Students (' Bob ', ' Alice ', ' Tim ') >>> print len (ss) 3
Task
The Fibonacci sequence is composed of 0, 1, 1, 2, 3, 5, 8 ...
Write a fib class where FIB (10) represents the first 10 elements of a sequence, and printFib prints the first 10 elements of a column, Len (Fib)) The number of columns can be returned correctly by 10.
Mathematical operations
The basic data types provided by Python int, float can do integer and floating point arithmetic, and the exponentiation operation.
However, arithmetic is not limited to int and float, it can also be rational number, matrix, etc.
To represent a rational number, you can use a rational class to represent:
Class Rational (object): def __init__ (self, p, q): SELF.P = p self.q = q
P and q are integers, which represent rational number p/q.
If you want rational to perform a + operation , you need to implement __add__ correctly:
Class Rational (object): def __init__ (self, p, q): SELF.P = p self.q = q def __add__ (self, R): return Rational (SELF.P * r.q + self.q * r.p, SELF.Q * r.q) def __str__ (self): return '%s/%s '% (SELF.P, self.q) __ repr__ = __str__
Now you can try the rational number addition:
>>> r1 = Rational (1, 3) >>> r2 = rational (1, 2) >>> print R1 + R25/6
Task
Although the rational class can do addition, but cannot do subtraction, exponentiation and division, continue to refine the rational class to achieve arithmetic.
Tips:
Subtraction Operation: __sub__
Multiplication Operation: __mul__
Division Operation: __div__
If the result of the operation is 6/8, it needs to be normalized to the simplest form 3/4 when displayed.
Def gcd (A, b): if b = = 0: return a return gcd (b, a% B) class Rational (object): def __init__ (self, p, q):
SELF.P = p self.q = q def __add__ (self, R): return Rational (SELF.P * r.q + self.q * r.p, SELF.Q * r.q) def __sub__ (self, R): return Rational (SELF.P * r.q-self.q * r.p, SELF.Q * r.q) def __mul__ (self, R): retur n Rational (SELF.P * R.P, SELF.Q * r.q) def __div__ (self, R): return Rational (SELF.P * r.q, SELF.Q * r.p) de F __str__ (self): g = gcd (SELF.P, self.q) return '%s/%s '% (self.p/g, self.q/g) __repr__ = __STR__R1 = R Ational (1, 2) r2 = Rational (1, 4) print R1 + r2print r1-r2print R1 * R2print R1/R2
Operation Result:
3/41/41/82/1
Type conversions
The rational class implements the rational number operation, but what if you want to convert the result to int or float ?
To examine the conversion of integers and floating-point numbers:
>>> Int (12.34) 12>>> float (12) 12.0
If you want to convert Rational to int, you should use:
r = Rational (5) n = Int (r)
for the int () function to work correctly, you only need to implement a special method __int__ ():
Class Rational (object): def __init__ (self, p, q): SELF.P = p self.q = q def __int__ (self): return SELF.P//SELF.Q #双斜杠: For floating-point division, the result is rounded
The results are as follows:
>>> Print int (rational (7, 2)) 3>>> print int (rational (1, 3)) 0
Similarly, for the float () function to work properly, you only need to implement a special method __float__ ().
Task
Please continue to refine rational so that it can be transformed into float.
Convert SELF.P to float type, then divide to get float:
Float (SELF.P)/SELF.Q
@property
Investigate Student class:
Class Student (object): def __init__ (self, Name, score): self.name = name Self.score = Score
When we want to modify the Scroe property of a Student , we can write this:
s = Student (' Bob ', s.score) = 60
But it can also be written like this:
S.score = 1000
Obviously, assigning a value directly to a property does not check the validity of the score.
If you are using two methods:
Class Student (object): def __init__ (self, Name, score): self.name = name Self.__score = Score def get_ Score (self): return self.__score def set_score (self, score): if score < 0 or score >: Raise ValueError (' invalid score ') Self.__score = Score
That way,S.set_score will get an error.
This use of the Get/set method to encapsulate access to a property is common in many object-oriented programming languages.
But writing S.get_score () and S.set_score () did not directly write S.score directly.
Is there a way to both worlds? ---- have.
Because Python supports higher-order functions, in functional programming we introduce the adorner function, which can be "decorated" with the Get/set method as an attribute call using the adorner function:
Class Student (object): def __init__ (self, Name, score): self.name = name Self.__score = score @ Property def score (self): return Self.__score @score. Setter def score (self, score): if Score < 0 or score >: raise ValueError (' invalid score ') Self.__score = Score
Note: The first score (self) is the Get method, decorated with @property, the second score (self, score) is the set method, decorated with @score.setter, @score. Setter is the previous @ The property is decorated by-product.
Now you can set the score as you would with properties:
>>> s = Student (' Bob ', ') >>> S.score = 60>>> print s.score60>>> S.score = 1000Traceba CK (most recent): ... Valueerror:invalid Score
Indicates that the set method is actually called for score assignment.
Task
If you do not define a set method , you cannot assign a value to the property, and you can create a read-only property.
Please add a grade attribute to the Student class and calculate a (>=80), B, C (<60) based on score .
Class Student (object): def __init__ (self, Name, score): self.name = name Self.__score = score @ Property def score (self): return Self.__score @score. Setter def score (self, score): if score < 0 or score >: raise ValueError (' invalid score ') Self.__score = score @property def grade ( Self): if Self.score <: return ' C ' if Self.score <: return ' B ' return ' A ' s = Student (' Bob ', ') print S.grades.score = 60print S.grades.score = 99print S.grade
Operation Result:
A
__slots__
Because Python is a dynamic language, any instance can dynamically add properties at run time.
If you want to limit the properties that you add, for example, theStudent class only allows you to add the 3 properties of name, gender , and score , you can take advantage of Python's special __ Slots__ to achieve.
As the name implies,__slots__ refers to a list of allowed properties for a class:
Class Student (object): __slots__ = (' name ', ' gender ', ' score ') def __init__ (self, name, gender, score): Self.name = name Self.gender = gender Self.score = Score
Now, take action on the instance:
>>> s = Student (' Bob ', ' Male ', ') >>> s.name = ' Tim ' # ok>>> s.score = # ok>>> s.gr ade = ' A ' Traceback (most recent call last): ... Attributeerror: ' Student ' object has no attribute ' grade '
The purpose of __slots__ is to limit the properties that the current class can have, and if you do not need to add any dynamic properties, using __slots__ can also save memory.
Task
Assuming that the person class defines name and genderthrough __slots__ , in the derived class Student , pass __ Slots__ continues to add the definition of score so that the Student class can implement the name, gender , and score 3 properties.
__call__
In Python, a function is actually an object:
>>> f = abs>>> f.__name__ ' abs ' >>> f (-123) 123
Because f can be called,F is called a callable object.
All functions are callable objects.
An instance of a class can also become a callable object, just to implement a special method __call__ ().
We turn the person class into a callable object:
class Person (object): def __init__ (self, Name, gender): self.name = name Self.gender = Gender def __ Call__ (self, Friend): " print ' My name is%s ... '% self.name print ' My friend is%s ... '% friend
You can now call directly to the person instance:
>>> p = person (' bob ', ' Male ') >>> p (' Tim ') My name is Bob ... My Friend is Tim ...
See P (' Tim ') you can't tell if p is a function or a class instance, so in Python, the function is also an object, and the difference between objects and functions is not significant.
Task
Improve the previously defined Fibonacci sequence:
Class Fib (object): ???
Please add a __call__ method to make the call simpler:
>>> f = Fib () >>> print F (10) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
To define parameters correctly: __call__ (self, num)
Python Advanced (v) custom class