返回顶部
首页 > 资讯 > 后端开发 > Python >Python魔法方法如何使用
  • 362
分享到

Python魔法方法如何使用

2023-07-04 20:07:16 362人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

这篇“python魔法方法如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python魔法方法如何使用”文章吧。pyt

这篇“python魔法方法如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python魔法方法如何使用”文章吧。

python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两个下划线包围来命名的

Python的魔法方法,也称为dunder(双下划线)方法。大多数的时候,我们将它们用于简单的事情,例如构造函数(__init__)、字符串表示(__str__, __repr__)或算术运算符(__add__/__mul__)。

迭代器的大小

我们都知道__len__方法,可以用它在容器类上实现len()函数。但是,如果您想获取实现迭代器的类对象的长度怎么办?

it = iter(range(100)) print(it.__length_hint__()) # 100 next(it) print(it.__length_hint__()) # 99  a = [1, 2, 3, 4, 5] it = iter(a) print(it.__length_hint__()) # 5 next(it) print(it.__length_hint__()) # 4 a.append(6) print(it.__length_hint__()) # 5

你所需要做的就是实现__length_hint__方法,这个方法是迭代器上的内置方法(不是生成器),正如你上面看到的那样,并且还支持动态长度更改。但是,正如他的名字那样,这只是一个提示(hint),并不能保证完全准确:对于列表迭代器,可以得到准确的结果,但是对于其他迭代器则不确定。但是即使它不准确,它也可以帮我们获得需要的信息,正如PEP 424中解释的那样

length_hint must return an integer (else a TypeError is raised) or NotImplemented, and is not required to be accurate. It may return a value that is either larger or smaller than the actual size of the container. A return value of NotImplemented indicates that there is no finite length estimate. It may not return a negative value (else a ValueError is raised).

编程

大部分很少看到的神奇方法都与元编程有关,虽然元编程可能不是我们每天都需要使用的东西,但有一些方便的技巧可以使用它。

一个这样的技巧是使用__init_subclass__作为扩展基类功能的快捷方式,而不必处理元类:

class Pet:     def __init_subclass__(cls, /, default_breed, **kwargs):         super().__init_subclass__(**kwargs)         cls.default_breed = default_breed  class Dog(Pet, default_name="German Shepherd"):     pass

上面的代码我们向基类添加关键字参数,该参数可以在定义子类时设置。在实际用例中可能会在想要处理提供的参数而不仅仅是赋值给属性的情况下使用此方法。

看起来非常晦涩并且很少会用到,但其实你可能已经遇到过很多次了,因为它一般都是在构建api时使用的,例如在sqlAlchemy或flask Views中都使用到了。

另一个元类的神奇方法是__call__。这个方法允许自定义调用类实例时发生的事情:

class CallableClass:     def __call__(self, *args, **kwargs):         print("I was called!")  instance = CallableClass()  instance() # I was called!

可以用它来创建一个不能被调用的类:

class NoInstances(type):     def __call__(cls, *args, **kwargs):         raise TypeError("Can't create instance of this class")  class SomeClass(metaclass=NoInstances):     @staticmethod     def func(x):         print('A static method')  instance = SomeClass() # TypeError: Can't create instance of this class

对于只有静态方法的类,不需要创建类的实例就用到了这个方法。

另一个类似的场景是单例模式——一个类最多只能有一个实例:

class Singleton(type):     def __init__(cls, *args, **kwargs):         cls.__instance = None         super().__init__(*args, **kwargs)      def __call__(cls, *args, **kwargs):         if cls.__instance is None:             cls.__instance = super().__call__(*args, **kwargs)             return cls.__instance         else:             return cls.__instance  class Logger(metaclass=Singleton):     def __init__(self):         print("Creating global Logger instance")

Singleton类拥有一个私有__instance——如果没有,它会被创建并赋值,如果它已经存在,它只会被返回。

假设有一个类,你想创建它的一个实例而不调用__init__。__new__ 方法可以帮助解决这个问题:

class Document:     def __init__(self, text):         self.text = text  bare_document = Document.__new__(Document) print(bare_document.text) # AttributeError: 'Document' object has no attribute 'text'  setattr(bare_document, "text", "Text of the document")

在某些情况下,我们可能需要绕过创建实例的通常过程,上面的代码演示了如何做到这一点。我们不调用Document(…),而是调用Document.__new__(Document),它创建一个裸实例,而不调用__init__。因此,实例的属性(在本例中为text)没有初始化,所欲我们需要额外使用setattr函数赋值(它也是一个魔法的方法__setattr__)。

为什么要这么做呢。因为我们可能会想要替代构造函数,比如:

class Document:     def __init__(self, text):         self.text = text          @claSSMethod     def from_file(cls, file):  # Alternative constructor         d = cls.__new__(cls)         # Do stuff...         return d

这里定义from_file方法,它作为构造函数,首先使用__new__创建实例,然后在不调用__init__的情况下配置它。

下一个与元编程相关的神奇方法是__getattr__。当普通属性访问失败时调用此方法。这可以用来将对缺失方法的访问/调用委托给另一个类:

class String:     def __init__(self, value):         self._value = str(value)      def custom_operation(self):         pass      def __getattr__(self, name):         return getattr(self._value, name)  s = String("some text") s.custom_operation()  # Calls String.custom_operation() print(s.split())  # Calls String.__getattr__("split") and delegates to str.split # ['some', 'text']  print("some text" + "more text") # ... works print(s + "more text") # TypeError: unsupported operand type(s) for +: 'String' and 'str'

我们想为类添加一些额外的函数(如上面的custom_operation)定义string的自定义实现。但是我们并不想重新实现每一个字符串方法,比如split、join、capitalize等等。这里我们就可以使用__getattr__来调用这些现有的字符串方法。

虽然这适用于普通方法,但请注意,在上面的示例中,魔法方法__add__(提供的连接等操作)没有得到委托。所以,如果我们想让它们也能正常工作,就必须重新实现它们。

自省(introspection)

最后一个与元编程相关的方法是__getattribute__。它一个看起来非常类似于前面的__getattr__,但是他们有一个细微的区别,__getattr__只在属性查找失败时被调用,而__getattribute__是在尝试属性查找之前被调用。

所以可以使用__getattribute__来控制对属性的访问,或者你可以创建一个装饰器来记录每次访问实例属性的尝试:

def logger(cls):     original_getattribute = cls.__getattribute__      def getattribute(self, name):         print(f"Getting: '{name}'")         return original_getattribute(self, name)      cls.__getattribute__ = getattribute     return cls  @logger class SomeClass:     def __init__(self, attr):         self.attr = attr      def func(self):         ...  instance = SomeClass("value") instance.attr # Getting: 'attr' instance.func() # Getting: 'func'

装饰器函数logger 首先记录它所装饰的类的原始__getattribute__方法。然后将其替换为自定义方法,该方法在调用原始的__getattribute__方法之前记录了被访问属性的名称。

魔法属性

到目前为止,我们只讨论了魔法方法,但在Python中也有相当多的魔法变量/属性。其中一个是__all__:

# some_module/__init__.py __all__ = ["func", "some_var"]  some_var = "data" some_other_var = "more data"  def func():     return "hello"  # -----------  from some_module import *  print(some_var) # "data" print(func()) # "hello"  print(some_other_var) # Exception, "some_other_var" is not exported by the module

这个属性可用于定义从模块导出哪些变量和函数。我们创建了一个Python模块…/some_module/单独文件(__init__.py)。在这个文件中定义了2个变量和一个函数,只导出其中的2个(func和some_var)。如果我们尝试在其他Python程序中导入some_module的内容,我们只能得到2个内容。

但是要注意,__all__变量只影响上面所示的* import,我们仍然可以使用显式的名称导入函数和变量,比如import some_other_var from some_module。

另一个常见的双下划线变量(模块属性)是__file__。这个变量标识了访问它的文件的路径:

from pathlib import Path  print(__file__) print(Path(__file__).resolve()) # /home/.../directory/examples.py  # Or the old way: import os print(os.path.dirname(os.path.abspath(__file__))) # /home/.../directory/

这样我们就可以结合__all__和__file__,可以在一个文件夹中加载所有模块:

# Directory structure: # . # |____some_dir #   |____module_three.py #   |____module_two.py #   |____module_one.py  from pathlib import Path, PurePath modules = list(Path(__file__).parent.glob("*.py")) print([PurePath(f).stem for f in modules if f.is_file() and not f.name == "__init__.py"]) # ['module_one', 'module_two', 'module_three']

最后一个我重要的属性是的是__debug__。它可以用于调试,但更具体地说,它可以用于更好地控制断言:

# example.py def func():     if __debug__:         print("debugging logs")      # Do stuff...  func()

如果我们使用

python example.py

正常运行这段代码,我们将看到打印出“调试日志”,但是如果我们使用

python -O example.py

优化标志(-O)将把__debug__设置为false并删除调试消息。因此,如果在生产环境中使用-O运行代码,就不必担心调试过程中被遗忘的打印调用,因为它们都不会显示。

以上就是关于“Python魔法方法如何使用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网Python频道。

--结束END--

本文标题: Python魔法方法如何使用

本文链接: https://lsjlt.com/news/347203.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python魔法方法如何使用
    这篇“Python魔法方法如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python魔法方法如何使用”文章吧。pyt...
    99+
    2023-07-04
  • python如何使用魔术方法
    这篇文章主要为大家展示了“python如何使用魔术方法”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何使用魔术方法”这篇文章吧。魔术方法魔术方法可...
    99+
    2024-04-02
  • python魔法方法 __ slots __怎么使用
    这篇文章主要讲解了“python魔法方法 __ slots __怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“python魔法方法 __&nb...
    99+
    2023-07-05
  • 详解Python中魔法方法的使用
    目录迭代器的大小元编程自省(introspection)魔法属性创建自己魔法方法python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两...
    99+
    2022-12-19
    Python魔法方法使用 Python魔法方法
  • 浅谈Python魔法方法
    特殊方法一览 在 Python 的学习和使用过程中, 你一定碰到过一些 特殊方法, 它们开头和结尾都有两条下划线, 也叫魔法方法 (Magic method), 或者 Dunder...
    99+
    2024-04-02
  • python魔法方法之__setattr__()
    目录前言:1、实例属性管理__dict__2、__setattr__()与__dict__3、重载__setattr__()必须谨慎总结:前言: python提供了诸多的魔法方法,其...
    99+
    2024-04-02
  • Python中的魔法方法
    python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两个下划线包围来命名的。Python的魔法方法,也称为dunder(双下划线)方法。大多数的时候,我们将它们用于简单的事情,例如构造函数(init)、字符串表示(s...
    99+
    2023-05-14
    Python 运算符
  • Python魔法方法指南
    (译)Python魔法方法指南 原作者: Rafe Kettler翻译: hit9原版(英文版) Repo:https://github.com/RafeKettler/magicmethods 简介 本指南归纳于我的几个月的博客,主题...
    99+
    2023-01-31
    指南 方法 魔法
  • Python 魔法方法详解
    据说,Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围,他们是面向对象的 Python 的一切。 他们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Py...
    99+
    2023-01-31
    详解 方法 魔法
  • 总结Python常用的魔法方法
    目录一、算数运算符的魔法方法二、反运算相关的魔法方法三、增量赋值运算四、一元操作符一、算数运算符的魔法方法 python2.2以后,对类和类型进行了统一,做法就是讲int(...
    99+
    2024-04-02
  • 详解Python常用的魔法方法
    目录一、python魔法方法二、运算符重载三、打印操作的魔法方法四、属性操作的魔法方法五、描述符六、定制序列七、迭代器一、python魔法方法 Python的魔法方法会在特定的情况下...
    99+
    2024-04-02
  • python魔法方法有哪些
    本篇文章给大家分享的是有关python魔法方法有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。python主要应用领域有哪些1、云计算,典型应用OpenStack。2、WE...
    99+
    2023-06-14
  • Python学习之魔法方法
      Python中会看到前后都加双下划线的函数名,例如 __init__(self),这类写法在Python中具有特殊的含义。如果对象使用了这类方法中的某一个,那么这个方法将会在特殊的情况下被执行,然而几乎不会直接调用此类方法。 如果没...
    99+
    2023-01-30
    方法 魔法 Python
  • Python魔方方法详解
    原文链接: https://fishc.com.cn/forum.phpmod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403 魔...
    99+
    2023-01-31
    魔方 详解 方法
  • Python常用的魔法方法是什么
    这篇文章将为大家详细讲解有关Python常用的魔法方法是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、python魔法方法Python的魔法方法会在特定的情况下自动调用,且他们的方法名通常被双下划...
    99+
    2023-06-15
  • 常用的Python魔法方法有哪些
    这期内容当中小编将会给大家带来有关常用的Python魔法方法有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、算数运算符的魔法方法python2.2以后,对类和类型进行了统一,做法就是讲int()、...
    99+
    2023-06-15
  • Python魔法方法的作用是什么
    Python魔法方法是一些特殊的方法,用于在特定的情况下自动调用。它们以双下划线()开头和结尾,如init,str__等。魔法方法允...
    99+
    2023-10-23
    Python
  • Python中魔法方法有哪些
    Python中魔法方法有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Python提供的魔法方法 魔术方法这里按照不同的类别有如下分类,用个表格给大家列举出来:看完上述内容...
    99+
    2023-06-19
  • Python学习【魔术方法】
    魔术方法 Python中,所有以双下划线“__”包围的方法(即定义在类中的函数)为魔术方法Magic Method。 构造和初始化 在使用classname()创造实例化对象时,会依次执行__new__和__init__两个方法。 __...
    99+
    2023-01-31
    魔术 方法 Python
  • python常用的魔法方法(双下划线)
    目录前言魔法方法__init__方法__new__方法__call__方法__str___方法__del___方法__enter__ & __exit__方法item系列方法...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作