在 Python 中使用统一化变量

发布于 2024-11-28 12:48:03 字数 687 浏览 5 评论 0原文

背景:我有一个类对带有寄存器的芯片进行建模,该芯片有一堆寄存器,其中一个是内置温度传感器的高温限制。

我有以下几点:

class foo():
  def __init__(self):
    # does not set self._hiTemp!
    ...
  def setHiTemp(self, t):
    self._hiTemp = t
  def getHiTemp(self):
    return self._hiTemp
  def checkHiTemp(self):
    return self._temp > self._hiTemp

我不在 __init__ 中声明 self._hiTemp 的原因是因为用户可能不关心芯片的温度感应功能。用户可以以不同的方式使用芯片,给这个变量赋予一个无意义的值是没有意义的。但是,如果用户在没有先设置的情况下尝试使用 self._hiTemp ,则使用未声明变量的错误比一些模糊错误(例如比较数字和 None )更容易调试/回溯(或者在某些情况下)甚至根本没有错误)。

一切都很顺利,直到我启动 pylint,当然我几乎到处都得到了 W0201:在 init 之外定义的属性。我只是想知道这种编码风格是否令人不悦,如果是,那么“Pythonic 方式”是什么。

谢谢

Background: I have a class modeling a chip with registers, the chip has a bunch of registers, one of them is a high temperature limit for the built-in temperature sensor.

I have the following:

class foo():
  def __init__(self):
    # does not set self._hiTemp!
    ...
  def setHiTemp(self, t):
    self._hiTemp = t
  def getHiTemp(self):
    return self._hiTemp
  def checkHiTemp(self):
    return self._temp > self._hiTemp

The reason that I don't declare self._hiTemp in the __init__ is because the user may not care about the temp-sensing capabilities of the chip. The user can be using the chip in different ways, and there is no meaning in giving this variable a meaningless value. However, if the user tries to use self._hiTemp without first setting it, the error of using undeclared variables is much easier to debug/backtrace than some obscure error like comparing numbers and None (or in some case even no errors at all).

This is all going fine until I start pylint, and of course I get W0201: Attribute defined outside init just about everywhere. I'm just wondering if this style of coding is frowned upon, and if so, what the "Pythonic way" is.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

高速公鹿 2024-12-05 12:48:04

我的方法是将其设置为 None 或其他一些“本质上”不会出现的哨兵值。然后,对于需要设置它的操作,请使用 assert 快速失败,以防调用者尝试不恰当地使用您的对象。

def __init__(self):
    self._hiTemp = None

def checkHiTemp(self):
    assert self._hiTemp is not None, 'Why you no set _hiTemp before checking it?'
    return self._temp > self._hiTemp

The way I'd do it is set it to None or some other sentinel value that doesn't occur 'in nature'. Then for operations that require it to be set, use an assert to fail fast in case the caller is trying to use your object inappropriately.

def __init__(self):
    self._hiTemp = None

def checkHiTemp(self):
    assert self._hiTemp is not None, 'Why you no set _hiTemp before checking it?'
    return self._temp > self._hiTemp
本宫微胖 2024-12-05 12:48:04

Python 不是 Java,所以不要像那样编写 getter 和 setter。你可以这样解决你的问题

class Foo(object):
    def __init__(self, hiTemp=None):
        self._hiTemp = hiTemp

    @property
    def hiTemp(self):
        if self._hiTemp is None:
            raise AttributeError("You have not initialized hiTemp")
        return self._hiTemp

    @hiTemp.setter
    def hiTemp(self, value):
        self._hiTemp = value

    def checkHiTemp(self):
        return self._temp > self._hiTemp

foo=Foo()
foo.hiTemp = 50
print foo.hiTemp # Prints 50

foo=Foo(hiTemp=20)
print foo.hiTemp # Prints 20

foo=Foo()
print foo.hiTemp # Raises exception

Python's not Java, so don't write getters and setters like that. You can solve your problem like this

class Foo(object):
    def __init__(self, hiTemp=None):
        self._hiTemp = hiTemp

    @property
    def hiTemp(self):
        if self._hiTemp is None:
            raise AttributeError("You have not initialized hiTemp")
        return self._hiTemp

    @hiTemp.setter
    def hiTemp(self, value):
        self._hiTemp = value

    def checkHiTemp(self):
        return self._temp > self._hiTemp

foo=Foo()
foo.hiTemp = 50
print foo.hiTemp # Prints 50

foo=Foo(hiTemp=20)
print foo.hiTemp # Prints 20

foo=Foo()
print foo.hiTemp # Raises exception
﹏半生如梦愿梦如真 2024-12-05 12:48:04

如果您希望通过方法设置对象的特定属性,那么总是有理由在初始化程序中使用它。您可以只使用 self._hiTemp=None 您已经通过前导 _ 将其声明为私有,因此用户会理解不要依赖它。

If you want a particular attribute of the object to be set via a method, then there could always be reason for it be available in the initializer. You can just use self._hiTemp=None You are already declaring it as private by leading _, so users will understand as not to rely on that.

窗影残 2024-12-05 12:48:04

通常使用值 None 来表示没有实际值。您可以将其初始化为 __init__ 中的值。在这种情况下,您还可以使用无意义的值(例如负数),并在 checkHiTemp 方法中检查该值,如果在没有正确初始化的值的情况下使用,则引发自定义异常。这是一个更有意义的错误。

It's customary to use the value None to mean no real value. You can initialize it to that in __init__. You might also use a meaningless value in this case, such as a negative number, and check for that in the checkHiTemp method, and raise a custom exception if used without a properly initialized value. That is an even more meaningful error.

開玄 2024-12-05 12:48:04

我认为从用户的角度来看,拥有正确的错误消息比未声明的变量错误更好。我会这样做:

def __init__(self):
    self._hiTemp = None

def setHiTemp(self, t):
    self._hiTemp = t

def getHitemp(self):
    if self._hiTemp is None:
        raise Exception('You need to setHiTemp() before using it.')
    else:
        return self._hiTemp

def checkHiTemp(self):
    if self._hiTemp is None:
        raise Exception('You need to setHiTemp() before using it.')
    else:
        return self._temp > self._hiTemp

I think from the user's perspective it would be better to have a proper error message than an undeclared variable error. I would do:

def __init__(self):
    self._hiTemp = None

def setHiTemp(self, t):
    self._hiTemp = t

def getHitemp(self):
    if self._hiTemp is None:
        raise Exception('You need to setHiTemp() before using it.')
    else:
        return self._hiTemp

def checkHiTemp(self):
    if self._hiTemp is None:
        raise Exception('You need to setHiTemp() before using it.')
    else:
        return self._temp > self._hiTemp
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文