资讯专栏INFORMATION COLUMN

python的解释器级别对象的实现方法

fredshare / 2672人阅读

摘要:最近在重构项目代码有个需求是需要声明一个变量然后任何了这个变量的模块当这个变量在其它地方更改了值以后这个变化都能反映出来乍看好像有点麻烦其实很简单就通常的想法来讲你用或一个类实例都能实现因为在使用它们时本质上还是一种引用的方式而不是像其它变

最近在重构项目代码, 有个需求是需要声明一个变量, 然后任何import了这个变量的模块, 当这个变量在其它地方更改了值以后, 这个变化都能反映出来, 乍看好像有点麻烦, 其实很简单.

就通常的想法来讲, 你用Dict, list或一个类实例都能实现. 因为在使用它们时, 本质上还是一种引用的方式, 而不是像其它变量是值复制, 所以它们的修改或变化是肯定能反映出来的

比如tornado的options, 没记错的话, 文档里写的什么解释器级别变量, 很高端的样子, 其实实现不难, 直接跳到代码

options = OptionParser()
"""Global options object.

All defined options are available as attributes on this object.
"""

Global的对象, 因为OptionParser的实例就一个options, 每次使用是怎么使用的呢

from tornado.options import options

每次都import的是这个实例, 而包括define在内的函数, 其实都是在对这个唯一的实例在进行操作而已, 代码中有这段

def define(name, default=None, type=None, help=None, metavar=None,
           multiple=False, group=None, callback=None):
    """Defines an option in the global namespace.

    See `OptionParser.define`.
    """
    return options.define(name, default=default, type=type, help=help,
                          metavar=metavar, multiple=multiple, group=group,
                          callback=callback)

另外一个令人容易想到的解释器级别的东西就是logger, logging.getLogger()也是声明解释器级别的对象, 而且还是线程安全的. 我们只需要在某个模块中声明一个logger, 然后在其它模块里

import logging

logger = logging.getLogger("xxname")

就行了

直接看代码

def getLogger(self, name):
        """
        Get a logger with the specified name (channel name), creating it
        if it doesn"t yet exist. This name is a dot-separated hierarchical
        name, such as "a", "a.b", "a.b.c" or similar.

        If a PlaceHolder existed for the specified name [i.e. the logger
        didn"t exist but a child of it did], replace it with the created
        logger and fix up the parent/child references which pointed to the
        placeholder to now point to the logger.
        """
        rv = None
        if not isinstance(name, basestring):
            raise TypeError("A logger name must be string or Unicode")
        if isinstance(name, unicode):
            name = name.encode("utf-8")
        _acquireLock()
        try:
            if name in self.loggerDict:
                rv = self.loggerDict[name]
                if isinstance(rv, PlaceHolder):
                    ph = rv
                    rv = (self.loggerClass or _loggerClass)(name)
                    rv.manager = self
                    self.loggerDict[name] = rv
                    self._fixupChildren(ph, rv)
                    self._fixupParents(rv)
            else:
                rv = (self.loggerClass or _loggerClass)(name)
                rv.manager = self
                self.loggerDict[name] = rv
                self._fixupParents(rv)
        finally:
            _releaseLock()
        return rv

这个getLogger函数最终调用的是Manager类的实例函数getLogger, 当你用的这个name不存在时, 通常是日志初始化时, 会声明一个Logger对象, 然后放到ManagerloggerDict中进行管理.

当你在别的地方也声明了这个name的logger时, Manager会发现loggerDict中已经有了, 直接拿出来用就行了. 其中还包括一些日志层级, hierarchy那些东西的处理, 不过这不是本文重点.

至于线程安全, 很简单, 代码里给加了线程锁. 这样打日志就不会东一块西一块了, 可惜多进程的日志标准库没有给进程安全的实现, 当然自己统一上传用socket处理或者用个process queue处理都是可以的.

如果想在允许多次实例化的情况下, 实现这种解释器级别变量呢?
那就是单例模式了, 在实例已经存在时调用一个函数对自己进行重载或更新即可

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38088.html

相关文章

  • 小李飞刀:ppppppython你好哇

    摘要:的被设定为装饰器可以帮助我们检查保证没有重复值。错误记录等解释器打印错误栈的信息,程序也结束了。将通过配置记录到日志文件中方便后续的排查。同理,指定后,和就不起作用了。启动的调试器,让程序以单步方式运行。 日常的写在前面 难得的周末,有大段的时间可以用来学习,体验就和工作日的晚上完全不一样了。好好的沉下心学习下~即刻很喜欢了! 好好学习的分割线 打打打鸡血!!!!!! 面向对象高级编程...

    greatwhole 评论0 收藏0
  • Python new 类方法和 init 实例方法以及单例模式简单讨论

    摘要:中的类都是单例模式一天,一同事问我这样一个问题。与方法属于新式类,即属于类。方法在实例被创建之后被调用,该方法仅仅是对方法创建的实例进行一些初始化操作。需要注意的是,在重写方法与方法的参数应该保持一致,否则会有发生。 Python 中的类都是单例模式? 一天,一同事问我这样一个问题。这是一个奇怪的问题,可能你也这么认为。这里先不做解释,我们先来看看 __new__ 和 __init__...

    FingerLiu 评论0 收藏0
  • 【数据科学系统学习】Python # 数据分析基本操作[二] pandas

    摘要:中面向行和面向列的操作基本是平衡的。用层次化索引,将其表示为更高维度的数据。使用浮点值表示浮点和非浮点数组中的缺失数据。索引的的格式化输出形式选取数据子集在内层中进行选取层次化索引在数据重塑和基于分组的操作中很重要。 我们在上一篇介绍了 NumPy,本篇介绍 pandas。 pandas入门 Pandas 是基于Numpy构建的,让以NumPy为中心的应用变的更加简单。 pandas...

    jayzou 评论0 收藏0
  • Python 面试」第二次更新

    摘要:结果为对于迭代器和生成器你知道哪些,它们分别应用于什么场景先介绍什么是可迭代的任何可用于循环的都是可迭代的。示例结果为,迭代器任何可以使用函数的都是迭代器,也可使用函数将可迭代对象变为迭代器。未写完,下次更新补上。 showImg(https://segmentfault.com/img/bVbuN3P); 阅读本文大约需要 8 分钟。 7.说一下 Python 中的装饰器 原理:利用...

    Yu_Huang 评论0 收藏0
  • [译] 从底层理解 Python 执行

    摘要:接下来,我们将注入到函数的字节码中。首先我们来看一下帧的参数所能提供的信息,如下所示当前帧将执行的当前的操作中的字节码字符串的索引经过我们的处理我们可以得知之后要被执行的操作码,这对我们聚合数据并展示是相当有用的。 原文链接: Understanding Python execution from inside: A Python assembly tracer 以下为译文 最近...

    wmui 评论0 收藏0

发表评论

0条评论

fredshare

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<