Python Advanced (v) custom class

Source: Internet
Author: User
Tags gcd

__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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.