Python学习手册之内部方法、操作符重

发布时间:2019-04-10 21:10:52编辑:auto阅读(1838)

     在上一篇文章中,我们介绍了 Python 的类和继承,现在我们介绍 Python 的内部方法、操作符重载和对象生命周期。

     查看上一篇文章请点击:https://www.cnblogs.com/dustman/p/10016359.html

    内部方法和操作符重载
    内部的方法
    Python 里有一些特殊的方法,也就是以双下划线开头并且以双下划线结尾的。它们可以是变量如 __doc__,也可以是方法如 __init__
    它们常见用途是操作符重载。这意味着可以自定义类的操作符,允许在这些类上使用加减乘除等运算符
    下面代码实现了__call__方法的对象,相当于重载了 (),可以实现调用功能。 实现非波纳契数列的类

    class Fib():
     def __call__(self, *args, **kwargs):
      ret = [1,1]
      num = int(args[0])
      if num == 1:
       return [1,]
      else:
       while len(ret)< num:
        ret.append(ret[-1]+ret[-2])
       return ret
    
    fib = Fib()
    print(fib(7))

    运行结果:

    >>>
    [1, 1, 2, 3, 5, 8, 13]
    >>>
    斐波那契数列,是数学上一个无穷数列。其形式为
    11235813……
    从第三项开始,每一项都是前两项之和。

    类运算重载的方法:
    __sub__ 表示运算符 -
    __mul__ 表示运算符 *
    __truediv__ 表示运算符 /
    __floordiv__ 表示运算符 //
    __mod__ 表示运算符 %
    __pow__ 表示运算符 **
    __and__ 表示运算符 &
    __xor__ 表示运算符 ^
    __or__ 表示运算符 |
    表达式 x + y 会被 Python 转换成 x.__add__(y)。但是,如果 x 没有实现 __add__ 方法并且 xy 是不同的类型,那么会调用 y.__radd__(x)
    对于上面提到的所有方法,都有相等的添加 r 前缀的方法。

    class Foo:
     def __init__(self,text):
      self.text = text
    
     def __mul__(self, other):
      line = "=" * len(other.text)
      return "\n".join([self.text,line,other.text])
    
    msg = Foo("Hello")
    hello = Foo("I like Python!")
    print(msg * hello)

    运行结果:

    >>>
    Hello
    ==============
    I like Python!
    >>>
    上面例子中,我们定义了类 Foo 的一个乘法方法。

    Python 同样提供了数据比较方面的方法。
    __it__ 表示运算符 <
    __le__ 表示运算符 <=
    __eq__ 表示运算符 ==
    __ne__ 表示运算符 !=
    __gt__ 表示运算符 >
    __ge__ 表示运算符 >=
    如果类没有实现 __ne__ ,则返回 __eq__ 相反的值。其他运算符之间没有这样的关系。

    class FooString():
     def __init__(self, name):
      self.name = name
    
     def __lt__(self, obj):
      return self.name == obj.name
    
    a = FooString("Python")
    b = FooString("Html")
    print(a < b)

    运行结果:

    >>>
    False
    >>>

    类中还有一些方法:
    __len__ 可用来做 len()
    __getitem__ 可用来做键值读取,适用于 [] 运算符。
    __setitem__ 设置给定值的值。
    __delitem__ 删除给定键对应的元素
    __iter__ 用来遍历对象
    __contains__ 用来做 in 操作
    还有许多其他的神奇方法,我们在这里就不一一谈论了,例如__call__ 用于将对象作为函数调用, __init____str__ 等等用于将对象转换为 Python 基础数据类型。

    #把一个类做成一个字典
    
    class Foo():
     def __init__(self):
      self.data = {}
     def __getitem__(self, key):
      print('__getitem__', key)
      return self.data.get(key)
    
     def __setitem__(self, key, value):
      print('__setitem',key, value)
      self.data[key] = value
    
     def __delitem__(self, key): #触发del
      print('__delitme__', key)
    
    obj = Foo() #实例化Foo
    obj['name'] = 'Python' #执行__setitem__
    print(obj['name']) #执行__getitem__
    
    del obj["name"]

    运行结果:

    >>>
    __setitem name Python
    __getitem__ name
    Python
    __delitme__ name
    >>>
    键值读取函数 __getitem__ 还可以根据表达式返回字典中的 key__setitem__ 设置 key 对应的 value 值。

    对象生命周期

    一个对象会经历三个生命周期:创建,操作,销毁。
    对象生命周期的第一阶段是它类变量和方法的定义。
    接下来下一阶段是这个实例的实例化。当 __init__ 被调用是,内存分配给存储实例。在此之前,调用类的 __new__ 方法,这通常仅在特殊情况下会被重写。在此以后,该对象就可以使用了。

    现在,其他代码可以通过调用对象上的函数或访问其属性与对象进行交互。最后它使用完毕并可被销毁。

    当一个对象被销毁时,分配给它的内存会被释放,并可以用于其他目的。
    当对象的引用计数达到零时,对象将销毁。引用计数是指引用对象的变量和其他元素的数量。如果没有任何变量引用它(它的引用计数为零),意味着没有任何东西可以与其交互,因此可以安全地删除它。在此也可以被删除。del 语句将对象的引用计数减少一个,这通常会导致对象被删除。del 语句调用对象的方法 __del__
    在不再需要对象是删除对象的过程称为垃圾收集。对象的引用计数在分配新名称或放在容器 (列表、元组或字典) 中时会增加。当使用 del 删除对象时,对象的引用计数会减少。当对象的引用计数达到零时,Python 会自动删除它。

    a=1       # 对象 1 被 变量a引用,对象1的引用计数器为1
    b=a       # 对象1 被变量b引用,对象1的引用计数器加1
    c=a       # 对象1 被变量c引用,对象1的引用计数器加1
    del a     #删除变量a,解除a对1的引用
    del b     #删除变量b,解除b对1的引用
    del c     #删除变量C,解除C对1的引用
    上面的例子,创建了一个含 1 的对象,对象的计数器加了 3 次,然后对象的计数器减了三次。这时该对象会被自动内存管理销毁。
    像 C 这样的低级语言没有这种自动内存管理系统。

     

     

     

    “数学就是用来把七成人筛出去的。”

关键字