Python's Custom class

Source: Internet
Author: User
Tags instance method

It __slots__ __xxx__ is important to note that these are similar to variables or function names, which have special uses in Python.

__slots__We already know how to use it, and __len__() we know it so that we can get class to len() function.

In addition, there are many special purpose functions in Python's class that can help us customize the class.

__str__

Let's first define a Student class and print an instance:

>>> class Student(object):... def __init__(self, name):... self.name = name...>>> print Student(‘Michael‘)<__main__.Student object at 0x109afb190>

Print out a bunch <__main__.Student object at 0x109afb190> , not pretty.

How can you print it well? Just define a good __str__() method and return a nice-looking string:

>>> class Student(object):... def __init__(self, name):... self.name = name... def __str__(self):... return ‘Student object (name: %s)‘ % self.name...>>> print Student(‘Michael‘)Student object (name: Michael)

This kind of printed example, not only good-looking, but also easy to see the important data inside the instance.

But careful friends will find that the direct knocking variable print is not used, the printed example is not good to see:

>>> s = Student(‘Michael‘)>>> s<__main__.Student object at 0x109afb310>

This is because the direct display of variable calls is not __str__() , but the __repr__() difference between the two is to return the string that the __str__() user sees, and the __repr__() string that the program developer sees, that __repr__() is, for debugging services.

The solution is to define one more __repr__() . But it's usually __str__() __repr__() the same as the code, so there's a lazy way to do it:

class Student(object):    def __init__(self, name): self.name = name def __str__(self): return ‘Student object (name=%s)‘ % self.name __repr__ = __str__
__iter__

If a class wants to be used for for ... in loops, like a list or a tuple, it must implement a __iter__() method that returns an iterative object, and then the python for loop constantly calls the iteration object's next() method to get the next value of the loop. Exits the loop until a stopiteration error is encountered.

For the Fibonacci sequence, we write a fib class that can be used for a For loop:

ClassHidef __init__< Span class= "params" (self): SELF.A, self.b = 0, 1 # Initialize two counters, a, b def __iter__ ( Self): return "
                  
                   # "function" 
                   def next (self): SELF.A, self.b = self.b, SELF.A + self.b # calculates the next value if self.a > 100000: # exit the Loop condition raise stopiteration (); return self.a # return next value        
                   

Now, try acting on the For loop with the FIB instance:

>>> for n in Fib():...     print n...11235...4636875025
__getitem__

Although the FIB instance can be used for a for loop, it looks a bit like the list, but using it as a list or not, for example, take the 5th element:

>>> Fib()[5]Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: ‘Fib‘ object does not support indexing

To act as a list to take out an element according to the subscript, you need to implement the __getitem__() method:

class Fib(object):    def __getitem__(self, n): a, b = 1, 1 for x in range(n): a, b = b, a + b return a

Now, you can click on any of the numbers to access the sequence:

>>> f = Fib()>>> f[0]1>>> f[1]1>>> f[2]2>>> f[3]3>>> f[10]89>>> f[100]573147844013817084101

But the list has a magical slicing method:

range(100)[5:10][5, 6, 7, 8, 9]

The

has an error for the FIB. The reason is that __getitem__ () passed in an argument that could be an int or a slice object slice , so make a decision:

class Fib(object):    def __getitem__(self, n): if isinstance(n, int): a, b = 1, 1 for x in range(n): a, b = b, a + b return a if isinstance(n, slice): start = n.start stop = n.stop a, b = 1, 1 L = [] for x in range(stop): if x >= start: L.append(a) a, b = b, a + b return L

Now try the fib slices:

>>> f = Fib()>>> f[0:5][1, 1, 2, 3, 5]>>> f[:10][1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

However, the step parameter is not processed:

f[:10:2][1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

There is no processing of negative numbers, so there __getitem__() is still a lot of work to be done to properly implement one.

In addition, if the object dict is considered, __getitem__() the argument may be an object that can be a key, for example str .

The corresponding method is to __setitem__() assign a value to the set as a list or a Dict object. Finally, there is a __delitem__() way to delete an element.

In short, by the above method, our own definition of the class and Python comes with the list, tuple, dict no difference, this is due to the dynamic language "duck type", do not need to force inheritance of an interface.

__getattr__

Normally, when we call a method or property of a class, it will be an error if it does not exist. For example Student , define a class:

class Student(object):    def __init__(self): self.name = ‘Michael‘

Call name Properties, no problem, but call a nonexistent score property, there is a problem:

>>> s = Student()>>> print s.nameMichael>>> print s.scoreTraceback (most recent call last): ...AttributeError: ‘Student‘ object has no attribute ‘score‘

The error message clearly tells us that the attribute was not found score .

To avoid this error, in addition to adding a score property, Python has another mechanism, which is to write a __getattr__() method that dynamically returns an attribute. Modify the following:

class Student(object):    def __init__(self): self.name = ‘Michael‘ def __getattr__(self, attr): if attr==‘score‘: return 99

When a non-existent property is called, for example score , the Python interpreter attempts to invoke __getattr__(self, ‘score‘) the property, so that we have a chance to return score the value:

>>> s = Student()>>> s.name‘Michael‘>>> s.score99

The return function is also perfectly possible:

class Student(object):    def __getattr__(self, attr): if attr==‘age‘: return lambda: 25

Just call the method to change to:

>>> s.age()25

Note that an existing attribute is called only if no attribute is found, __getattr__ for example name , it is not located in __getattr__ .

Also, notice that any call s.abc will return None , because the default return that we define is __getattr__ None . To allow class to respond to only a few specific properties, we are going to throw the error according to the Convention AttributeError :

class Student(object):    def __getattr__(self, attr): if attr==‘age‘: return lambda: 25 raise AttributeError(‘\‘Student\‘ object has no attribute \‘%s\‘‘ % attr)

This actually allows all the properties and method invocations of a class to be dynamically processed, without any special means.

What is the actual function of this fully dynamic invocation? The effect is that it can be called for a completely dynamic situation.

As an example:

Now a lot of websites are doing rest API, such as Sina Weibo, watercress What, call API URL similar:

http://api.server/user/friendshttp://api.server/user/timeline/list

If you want to write the SDK, to each URL corresponding to the API to write a method, it is exhausting, and, once the API changes, the SDK will be changed.

With completely dynamic __getattr__ , we can write a chain call:

class Chain(object):    def __init__(self, path=‘‘): self._path = path def __getattr__(self, path): return Chain(‘%s/%s‘ % (self._path, path)) def __str__(self): return self._path

Try:

>>> Chain().status.user.timeline.list‘/status/user/timeline/list‘

In this way, regardless of the API changes, the SDK can be based on the URL to achieve a full dynamic call, and not with the increase of the API to change!

There are rest APIs that put parameters in URLs, such as GitHub's API:

GET /users/:user/repos

When calling, you need to :user replace the actual user name. If we can write a chain call like this:

Chain().users(‘michael‘).repos

It is very convenient to invoke the API. Interested children's shoes can try to write them out.

__call__

An object instance can have its own properties and methods, which we use to invoke when we invoke an instance method instance.method() . Can you call it directly on the instance itself? Similar instance() ? In Python, the answer is yes.

In any class, you can simply __call__() invoke the instance by defining a method. Take a look at the example:

class Student(object):    def __init__(self, name): self.name = name def __call__(self): print(‘My name is %s.‘ % self.name)

The method is called as follows:

>>> s = Student(‘Michael‘)>>> s()My name is Michael.

__call__()You can also define parameters. Making a direct call to an instance is like calling a function, so you can think of the object as a function and the function as an object because there is no fundamental difference between the two.

If you look at the object as a function, then the function itself can be created dynamically at runtime, because instances of the class are created at run time, so we blur the bounds of the object and the function.

So, how do you tell if a variable is an object or a function? In fact, more often, we need to determine whether an object can be called, the object that can be called is an Callable object, such as the function and the class instance we have defined above __call()__ :

>>> callable(Student())True>>> callable(max)True>>> callable([1, 2, 3])False>>> callable(None)False>>> callable(‘string‘)False

Through callable() the function, we can determine whether an object is a callable object.

Reference Link: https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/ 0013946328809098c1be08a2c7e4319bd60269f62be04fa000

Python's 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.