python重载符(二)--__contains__、__repr__和__radd__等

 

下面时latex源代码,大家可以自己编译一下:

\subsubsection{成员关系:$\_\_contains\_\_, \_\_iter\_\_, \_\_getitem\_s\_$}

\par{

    \begin{itemize}

        \item 首先再强调一个特别的地方,为什么:for i in Class()这样的语句能够被执行?因为这Class()是一个类,并且for语句调用了$\_\_iter\_\_$方法,于是这个for循环实际就是$\_\_iter\_\_$方法的调用,所以自然可以执行啦。

        \item 另外注意,$\_\_iter\_\_$方法被调用时,会一直调用到raise StopIteration,所以比如只有for i in iter([1, 2, 3]): 但是实际上$\_\_next\_\_$会执行4次,只是最后一次到raise StopIteration,for循环不打印出来罢了。

        \item 总的来说,$\_\_contains\_\_$会拦截成员关系,比如形如x in class()的判断会优先使用$\_\_contains\_\_$,但是如果$\_\_contains\_\_$没有在类里被重载,那么就会优先使用$\_\_iter\_\_$, 但如果$\_\_iter\_\_$也没使用,就会使用$\_\_getitem\_\_$重载符。如果都没有,就自然使用默认的重载符功能。

        \item $\_\_contains\_\_$:一个重载关系符号in的操作,比如:

        \begin{lstlisting}[language = {python}]

    class Person(object):

        def __init__(self,name,age):

          self.name = name

          self.age = age

        def __contains__(self,param1):

          return True if param1 in self.__dict__.keys() else False

>>> p = Person('Robby Krieger',23)

>>> 'name' in p

    True

    #这里在in左边的对象是__contains__中的可变参数,右边的实例p即参数中的self参数。


 

        \end{lstlisting}

        \item 猜测注释掉$\_\_contains\_\_$后,in的实现过程是,首先还是会考虑$\_\_iter\_\_$方法,依靠它和$\_\_next\_\_$逐一返回迭代值和in右边的属比较,直到True或者False停止。

        \item 所以可见,尽管注释掉$\_\_contains\_\_$后,也不是$\_\_iter\_\_$直接替换$\_\_contains\_\_$,而是还有一些别的操作,结合$\_\_contains\_\_$一起做出结果判断。

        \item $\_\_iter\_\_$和yield结合起来用可以代替$\_\_iter\_\_$和$\_\_next\_\_$组合。因为这样for循环每次调用时,会受到yield一次又一次返回的值。

    \end{itemize}

}

\subsubsection{$\_\_getattr\_\_$ and $\_\_setattr\_\_$}

\par{

    \begin{itemize}

        \item 首先$\_\_getattr\_\_$是在进行实例.属性(某个不存在属性)这样的点操作时会调用的方法。

        \item 其次$\_\_setattr\_\_$:

        首先注意下面这个属性赋值的重载方法:

        \begin{lstlisting}[language  = {Python}]

def __setattr__(self, key, value):

    object.__setattr__(self, key, value)

    #这里直接接一句object.__setattr__(self, key, value)表示其实根本不需要重载。

    #这个重载主要就是想,对于value是base类型的的哪些,我们做一些特殊操作,即假如 value 是 Base 检查, 放到队列中

    #而数据类型本身因为object.__setattr__(self, key, value)的出现,仍然使用原来的赋值操作。

    if isinstance(value, Base):

        p: Base = value

        if p.pin_type == PinType.Input:

            self.__in_data.insert(p.index, p)

        else:

            self.__out_data.insert(p.index, p)

    pass

    #其次如果是 object.__setattr__(self, attr, value + 10),首先它能比避免循环是因为调用父类的赋值方法进行赋值,且又不是把value赋值给attr,而是把value+10赋值给attr,从而完成重载。

        \end{lstlisting}

        \item $\_\_delattr\_\_$和$\_\_setattr\_\_$用法类似,要不用$\_\_dict\_\_$要不用父类来避免循环调用。

   

    \end{itemize}

}

\subsubsection{字符串显示$\_\_repr\_\_$ and $\_\_str\_\_$}

\begin{itemize}

    \item $\_\_repr\_\_$: 将会在函数str(), 或者打印这个类的时候被调用。

    \item $\_\_str\_\_$支持print()和str()时候的调用,不过print()和str()下$\_\_str\_\_$被重载时,会优先于$\_\_repr\_\_$。但是其他场景只会用$\_\_repr\_\_$(如交互式和命令行显示)

    \item 所以$\_\_repr\_\_$用于全场景,而 $\_\_str\_\_$优先使用于打印和str()函数。

    \item 注意这俩重载符只会返回字符串,所以如果时其他类型,注意使用str()函数或者$ \% $符号

\end{itemize}

\subsubsection{右侧加法和原位置加法$\_\_radd\_\_$ and $\_\_iadd\_\_$}

\par{

    \begin{itemize}

        \item 简单来说,$\_\_radd\_\_$用来处理实例在左边的情况。

        \item 如果想处理实例在右边的情况,要么重写$\_\_radd\_\_$调用$\_\_add\_\_$,要么直接在类里面声明:$\_\_radd\_\_$ = $\_\_add\_\_$

    \end{itemize}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值