ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

6.4、定制类

2020-04-05 14:56:43  阅读:244  来源: 互联网

标签:__ users Chain self michael 6.4 path 定制


__str__

 

 

直接显示变量调用的不是__str__(),而是__repr__(),两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。

解决办法是再定义一个__repr__()。但是通常__str__()__repr__()代码都是一样的

 __repr__=__str__

 

 __iter__

如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

__getitem__

要表现得像list那样按照下标取出元素,需要实现__getitem__()方法:

 

 不能切片

 

 

 没有对step做处理,也没有负数处理

__getattr__

 

 

 def __getattr__(self,attr)

注意,只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。

任意调用如s.abc都会返回None,这是因为我们定义的__getattr__默认返回就是None。要让class只响应特定的几个属性,我们就要按照约定,抛出AttributeError的错误:

 

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

 

 

 

__call__

 

一个对象实例可以有自己的属性和方法,当我们调用实例方法时,我们用instance.method()来调用。能不能直接在实例本身上调用呢?在Python中,答案是肯定的。

 

任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用

 

 怎么判断一个变量是对象还是函数呢?其实,更多的时候,我们需要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象,比如函数和我们上面定义的带有__call__()的类实例:

 

 

 

 

 

class Chain(object):
    def __init__(self, path=''):
       self.__path = path

   def __getattr__(self, path):
       return Chain('%s/%s' % (self.__path, path))

   def __call__(self, path):
       return Chain('%s/%s' % (self.__path, path))

   def __str__(self):
       return self.__path

   __repr__ = __str__

   print(Chain().users('michael').repos) # /users/michael/repos

 

Step 1:
Chain()  # 实例化
Step 2:
Chain().users
# 由于没有给实例传入初始化对应属性的具体信息,从而自动调用__getattr__()函数,从而有:
Chain().users = Chain('\users') # 这是重建实例
Step 3:
Chain().users('michael')
Chain().users('michael') = Chain('\users')('michael') # 这是对实例直接调用,相当于调用普通函数一样
# 关键就在这步,上面的朋友没有说明晰(并不是说你们不懂),这一步返回的是Chain('\users\michael'),再一次重建实例,覆盖掉Chain('\users'),
#记 renew = Chain('\users\michael'), 此时新实例的属性renew.__path = \users\michael;
Step 4:
Chain().users('michael').repos
# 这一步是查询renew实例的属性repos,由于没有这一属性,就会执行__getattr__()函数,再一次返回新的实例Chain('\users\michael\repos')并且覆盖点之前的实例,
# 这里记 trinew =Chain('\users\michael\repos'),不要忘了,一单定义了一个新的实例,就会执行__init__方法;
Step 5:
print(Chain().users('michael').repos) = print(trinew)  #由于我们定义了__str__()方法,那么打印的时候就会调用此方法,据此方法的定义,打印回来的是trinew的__path属#性,即——\users\michael\repos  。至此,我们也把所有定义的有特殊用的方法都用上了,完毕。

 

标签:__,users,Chain,self,michael,6.4,path,定制
来源: https://www.cnblogs.com/soberkkk/p/12637224.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有