6.4定制类

Posted soberkkk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6.4定制类相关的知识,希望对你有一定的参考价值。

__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(‘usersmichael‘),再一次重建实例,覆盖掉Chain(‘users‘),
#记 renew = Chain(‘usersmichael‘), 此时新实例的属性renew.__path = usersmichael;
Step 4:
Chain().users(‘michael‘).repos
# 这一步是查询renew实例的属性repos,由于没有这一属性,就会执行__getattr__()函数,再一次返回新的实例Chain(‘usersmichael
epos‘)并且覆盖点之前的实例,
# 这里记 trinew =Chain(‘usersmichael
epos‘),不要忘了,一单定义了一个新的实例,就会执行__init__方法;
Step 5:
print(Chain().users(‘michael‘).repos) = print(trinew)  #由于我们定义了__str__()方法,那么打印的时候就会调用此方法,据此方法的定义,打印回来的是trinew的__path属#性,即——usersmichael
epos  。至此,我们也把所有定义的有特殊用的方法都用上了,完毕。

 

以上是关于6.4定制类的主要内容,如果未能解决你的问题,请参考以下文章

Gradle 引入本地定制 jar 包

VsCode 代码片段-提升研发效率

6.4 Java 8的日期时间类

2017.12.13T19_B2_6.4内部类

如何通过单击片段内的线性布局从片段类开始新活动?下面是我的代码,但这不起作用

6.4-数据结构&算法-模板/函数模板/类模板/特化