七个Python问题,来扫扫盲

发表于:2023-1-06 09:38

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:somenzz    来源:Python七号

  你可能知道 Python 里面的魔法函数,比如 __add__ 和 __sub__ 代表 + - 运算符,表示 obj +/- something,但你可能不知道还有一个 __radd__,__rsub__ 函数,可以表示 something +/- obj。
  这 7 个问题,我是有收获的,整理如下:
  1、反射算术运算符
  你可能知道 Python 里面的魔法函数,比如 __add__? 和 __sub__? 代表 + - 运算符,表示 obj +/- something,但你可能不知道还有一个 __radd__,__rsub__ 函数,可以表示 something +/- obj。
  举例如下:
  class Dog:
      def __add__(self, other):
          return "from __add__"
      def __radd__(self, other):
          return "from __radd__"
  dog = Dog()
  print(dog + 1)   # from __add__
  print(1 + dog)   # from __radd__
  2、__getattr__ vs __getattribute__
  __getattr__? 魔术方法只有在我们试图获取不存在的属性时才会被调用,__getattribute__ 在每次我们尝试访问属性时都会被调用。
  代码如下:
  class Dog:
      def __init__(self, name, age):
          self.name = name
          self.age = age
      def __getattr__(self, key):
          return f"{key} not found"
  dog = Dog("taidi", 5)
  print(dog.name)    # taidi
  print(dog.age)     # 5
  print(dog.breed)   # breed not found
  class Dog:
      def __init__(self, name, age):
          self.name = name
          self.age = age
      def __getattribute__(self, key):
          return f"{key} not found"
  dog = Dog("taidi", 5)
  print(dog.name)    # name not found
  print(dog.age)     # age not found
  print(dog.breed)   # breed not found
  3、super().__init__() 的另一种写法
  class Animal:
      def __init__(self, name, age):
          self.name = name
          self.age = age
  class Dog(Animal):
      def __init__(self, name, age, breed):
          super().__init__(name, age)
          self.breed = breed
  等价于:
  class Animal:
      def __init__(self, name, age):
          self.name = name
          self.age = age
  class Dog(Animal):
      def __init__(self, name, age, breed):
          Animal.__init__(self, name, age)
          self.breed = breed
  请注意,Animal.__init__(self, name, age) 不能少了 self 参数。
  4、检查子类的方法
  class Animal: pass
  class Dog(Animal): pass
  class Cat(Animal): pass
  class GermanSheperd(Dog): pass
  print(Animal.__subclasses__())
  # [<class '__main__.Dog'>, <class '__main__.Cat'>]
  不过,.__subclasses__() 只能检查直接子类。
  5、多重集成时,同名函数,子类用的是哪一个?
  class A:
      def test(self):
          print("A")
  class B:
      def test(self):
          print("B")
  class C(A, B):
      pass
  C().test()   # A
  A 和 B 都有 test 方法,那么 C 到底集成了哪一个呢?在 Python 中,最左边的类优先。
  在这里,A 是最左边的父类,因此 A 的 test 方法被集成。
  多充继承让人困惑,不用为好。
  6 __invert__ 魔法函数
  class Dog:
      def __invert__(self):
          return "test"
  dog = Dog()
  print(~dog)   # test
  ~ 运算符代表“按位非”,通常用于反转内容。一个更有意义的例子如下:
  class Coordinate:
      def __init__(self, x, y):
          self.x = x
          self.y = y
      def __str__(self):
          return f"({self.x}, {self.y})"
      def __invert__(self):
          return Coordinate(-self.x, -self.y)
  a = Coordinate(3, 4)
  b = ~a
  print(a, b)   # (3, 4) (-3, -4)
  7、不使用 class 来创建类
  def init(self, name, age):
      self.name = name
      self.age = age
  def bark(self):
      print("woof")
  Dog = type("Dog", (), {"__init__":init, "bark":bark})
  dog = Dog("taidi", 10)
  print(dog.name)
  print(dog.age)
  # taidi
  # 10
  在这里,我们将 3 个参数传递给 type 以创建我们的类。
  第一个参数 __name__? 是类的名称 第二个参数 __bases__? 是一个包含父类的元组 第三个参数 __dict__ 是一个包含属性和方法的字典。
  等价于:
  class Dog:
      def __init__(self, name, age):
          self.name = name
          self.age = age
      def bark(self):
          print("woof")
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号