python with语句有啥用

Posted

tags:

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

参考技术A

如果不用with语句,代码如下:

file = open("/tmp/foo.txt")

data = file.read()

file.close()

这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

file = open("/tmp/foo.txt")

try:

    data = file.read()

finally:

    file.close()

   


Python 元类有啥用?

【中文标题】Python 元类有啥用?【英文标题】:What are Python metaclasses useful for?Python 元类有什么用? 【发布时间】:2011-01-01 15:06:26 【问题描述】:

不能以任何其他方式使用的元类可以做什么?

Alex Martelli 告诉这里有些任务没有元类就无法完成Python metaclasses vs class decorators 我想知道哪些是?

【问题讨论】:

我记得我在某处读到过这样的关于元类的文章,引用松散的话:“如果你不得不问它们有什么用,这意味着你不需要它们”。 +1,有趣的问题。 我不确定“不能以任何其他方式完成”是一个有用的标准。几乎所有事情都可以通过许多不同的方式来完成,这完全取决于它是多么容易/自然。 应该有一种——最好只有一种——明显的方法。 :) @Juanjo Conti:你说得对,但我想说的是,很多时候,语法只是为了让事情更自然一些。例如,List Comprehensions 不会做任何你不能用 for's 做的事情,但它们可以让一些事情变得更自然。 (很抱歉,如果这听起来很挑剔,那不是我的想法......我只是想说几乎所有可以在没有特定功能的情况下完成)。 @Edan,执行以下任务:创建一个类对象 X,使 print X 发出“现在时间是上午 8:43”(上午 8:43,更一般地说是当前时间) .如果没有自定义元类,您将如何这样做 【参考方案1】:

如果你想让类对象(而不是类对象的实例)配备“特殊的自定义行为”,元类是必不可少的,因为对象的行为取决于 上的特殊方法对象的类型,而类对象的类型正是元类的同义词。

例如,如果您想要一个类对象 X,使得“print X”发出“Time is now 8:46am”(上午 8:46,或者更一般地说,当前时间),这一定意味着 @987654321 @(AKA X 的元类)有一个特殊的自定义 __str__ 方法——如果你想赋予诸如 X + Y 之类的表达式含义,其中 X 和 Y 都是类对象,或者类似地(使用各种适用的特殊方法),或者X[23](这里 X 又是一个类对象)等等。

现在大多数其他自定义任务(在 Python 2.6 或更高版本中)使用类装饰器更容易实现,它可以在 class 语句结束后立即更改类对象。在其他一些情况下这是不可行的,因为更改必须尽早进行才能产生任何效果(例如,设置或更改 __slots__)。

在 Python 3 中,元类获得了一点额外的用处:元类现在可以选择指定在执行 class 语句主体期间填充的映射对象(默认情况下,它是一个普通的 dict)。这允许在类主体中保留和使用名称绑定的顺序(而普通的dict 失去顺序),当类必须在某个特定的“字段”中具有“字段”时,这有时很好顺序(例如,将 1:1 映射到 C struct、CSV 文件或 DB 表中的一行等)——在 Python 2.* 中必须冗余指定(通常带有一个额外的类属性一个序列,因此确实保留了顺序),并且 Python 3 元类的这个特性允许删除冗余。

【讨论】:

【参考方案2】:

为您的编程增加额外的灵活性:

但根据Metaclass programming in Python,您可能不需要它们(还)

元类比 99% 的用户所担心的更深奥。如果你想知道自己是否需要它们,你就不需要(真正需要它们的人肯定知道他们需要它们,并且不需要解释为什么)。

-- Python 大师 Tim Peters

【讨论】:

思考面向方面的编程。我发布的链接包含全面的解释和代码示例。 @OscarRyz 链接好像坏了【参考方案3】:

我经常使用元类,它们是工具箱中非常强大的工具。有时你的问题解决方案可以更优雅,代码更少,有它们比没有它们。

我发现自己最常使用元类的事情是在类创建期间对类属性进行后处理。例如,在适当的地方为对象设置name 属性(例如 Django ORM 的工作方式):

class AutonamingType(type):
    def __init__(cls, name, bases, attrs):
        for k,v in attrs.iteritems():
            if getattr(v, '__autoname__', False):
                v.name = k

class Autonamer(object):
    __metaclass__ = AutonamingType

如果你有这个作为工具,并且你使用的类必须知道它的name,然后才能知道do_something()

class Foo(object):
    __autoname__ = True
    def __init__(self, name=None):
        self.name = name
    def do_something(self):
        if self.name is None:
            raise ValueError('name is None')
        # now, do something

它可以使您的其余代码在这之间有所不同:

class Bar(object):
    myfoo1 = Foo('myfoo1')
    myfoo2 = Foo('myfoo2')
    myfoo3 = Foo('myfoo3')

还有这个:

class Baaz(Autonamer):
    myfoo1 = Foo()
    myfoo2 = Foo()
    myfoo3 = Foo()

从而减少重复(以及变量名称和分配名称可能不同步的可能性)。

【讨论】:

要在没有元类的情况下实现类似的自动命名行为,从 Python 3.6 开始,您可以使用 set_name 方法将 Foo 转换为描述符。【参考方案4】:

如果你正在寻找使用元类机制的例子,你可以阅读django.forms的源代码。

表单定义的声明式风格是通过元类实现的。

【讨论】:

【参考方案5】:

它们很少需要,但在您希望将行为添加到对象的基本行为的地方很有用——比较面向方面的编程或在 Hibernate 等持久性框架中完成的检测。

例如,您可能需要一个持久化或记录每个新对象的类。

【讨论】:

【参考方案6】:

可能没有什么可以完全使用元类来完成,但对于某些人(包括我的)来说,这是一个可以使用的有趣工具。请注意不要滥用,因为这可能很棘手。

例如,我在最近的一个项目中使用了元编程。这是一个 OpenOffice 计算表,它使用一些 pyUNO 宏生成一些带有信息的文件。有一张表格向用户显示要填写的信息,其他表格可用于描述元素的种类及其属性。然后,用户可以选择元素的数量和每个元素的类型,并生成文件。 该宏将按照每张纸上的配置通过元编程创建一个类。然后,用户可以实例化每个类并生成对象。

它可以在没有元编程的情况下完成,但对我来说,使用元编程功能来完成它似乎很自然。

【讨论】:

【参考方案7】:

查看 Django 源代码 - 例如元类用于生成模型。

http://code.djangoproject.com/wiki/DynamicModels

在内部,Django 使用元类 根据您的课程创建模型 在您的源代码中提供。没有 涉及太多细节, 意味着而不是你的课程 作为实际模型,Django 收到你的班级的描述, 它用于在其中创建模型 地点。

【讨论】:

【参考方案8】:

第一位评论员指出,元类here 的使用是“一块宝石”,可以帮助他追踪(许多)“天”内发生的意外错误。

【讨论】:

以上是关于python with语句有啥用的主要内容,如果未能解决你的问题,请参考以下文章

SQL SERVER里面的with语句有啥作用?用过的师兄请帮忙

浅谈 Python 的 with 语句(转)

Python 的with语句

Python with语句

理解Python的With语句

python with语句