如何在Python中logging类的属性?
我正在编写一个轻量级类,其属性旨在公开访问,并且有时仅在特定的实例化中被覆盖。 Python语言中没有规定为类属性或任何属性创build文档string。 如果有的话,什么是公认的方式来logging这些属性? 目前我正在做这样的事情:
class Albatross(object): """A bird with a flight speed exceeding that of an unladen swallow. Attributes: """ flight_speed = 691 __doc__ += """ flight_speed (691) The maximum speed that such a bird can attain. """ nesting_grounds = "Raymond Luxury-Yacht" __doc__ += """ nesting_grounds ("Raymond Luxury-Yacht") The locale where these birds congregate to reproduce. """ def __init__(self, **keyargs): """Initialize the Albatross from the keyword arguments.""" self.__dict__.update(keyargs)
这将导致包含初始标准文档string部分的类的文档string以及通过对__doc__
进行扩充赋值为每个属性添加的行。
虽然这种风格似乎并没有明确禁止在文档string风格的指导方针 ,也没有提到作为一个选项。 这样做的好处在于,它提供了一种方法来将属性与定义一起文档化,同时仍然创build一个可呈现的类文档string,并且避免必须编写重复来自文档string的信息的注释。 我仍然有点恼火,我不得不写两次属性。 我正在考虑使用文档string中的值的string表示,以至less避免重复的默认值。
这是否违反了特别的社区公约? 好吗? 有没有更好的办法? 例如,可以创build一个包含属性值和文档string的字典,然后将这些内容添加到类__dict__
和docstring中,直到类声明结束; 这将缓解需要input两次属性名称和值。 编辑 :我认为这最后一个想法实际上是不可能的,至less不是没有从数据dynamic地构build整个类,这似乎是一个非常糟糕的主意,除非有其他的理由这样做。
我对python很陌生,仍然在编写代码风格的细节,所以无关的批评也是受欢迎的。
为了避免混淆:术语属性在python中有特定的含义 。 你所说的是我们所说的类属性 。 由于他们总是通过他们的class级行事,所以我发现把他们logging在class级的文档string中是有道理的。 像这样的东西:
class Albatross(object): """A bird with a flight speed exceeding that of an unladen swallow. Attributes: flight_speed The maximum speed that such a bird can attain. nesting_grounds The locale where these birds congregate to reproduce. """ flight_speed = 691 nesting_grounds = "Throatwarbler Man Grove"
我觉得比你的例子中的方法更容易。 如果我真的想要一个属性值的副本出现在文档string中,我会把它们放在每个属性的描述旁边或下面。
编辑:
请记住,在Python中,文档string是它们所logging对象的实际成员,而不仅仅是源代码注释。 由于类属性variables本身不是对象,而是对象的引用,所以他们没有办法保存自己的文档string。 我想你可以在引用上为docstring创build一个案例,也许可以描述“应该在这里”而不是“实际在这里”,但是我发现在包含类doc的string中这样做很容易。
您引用了PEP257: 文档string约定,在部分是什么是文档string :
在Python代码中出现的string文字也可以作为文档。 它们不被Python字节码编译器识别,并且不能作为运行时对象属性(即未分配给__doc__)访问,但可以通过软件工具提取两种types的额外文档string:
在模块,类或__init__方法的顶级简单赋值之后立即出现的string文字被称为“属性文档string”。
这在PEP 258:Attribute docstrings中有更详细的解释。 正如上面解释的那样。 属性不是可以拥有__doc__的对象,所以它们不会出现在help()
或pydoc中。 这些文档只能用于生成的文档。
但目前很less有工具使用它们。
旧的Epydoc使用它们 ,Sphinx在v0.6中引入了它,并在v1.1中进行了扩展。 狮身人面像可以在作业之前的一行上使用文档string,也可以在分配之后的特殊注释中使用。
请参阅“ 狮身人面像手册”中的指令自动属性以及那里的属性文档的示例。
你可能会滥用属性来达到这个效果。 属性包含getter,setter,deleter 和docstring 。 天真地,这将变得非常冗长:
class C: def __init__(self): self._x = None @property def x(self): """Docstring goes here.""" return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x
那么你将有一个属于Cx的文档string:
In [24]: print(Cx__doc__) Docstring goes here.
要做到这一点很多的属性是麻烦的,但你可以想象一个助手函数myprop:
def myprop(x, doc): def getx(self): return getattr(self, '_' + x) def setx(self, val): setattr(self, '_' + x, val) def delx(self): delattr(self, '_' + x) return property(getx, setx, delx, doc) class C: a = myprop("a", "Hi, I'm A!") b = myprop("b", "Hi, I'm B!") In [44]: c = C() In [46]: cb = 42 In [47]: cb Out[47]: 42 In [49]: print(Cb__doc__) Hi, I'm B!
然后,调用Pythons交互式help
将给:
Help on class C in module __main__: class C | Data descriptors defined here: | | a | Hi, I'm A! | | b | Hi, I'm B! which I think should be pretty much what you're after.
编辑 :我现在意识到,我们可以避免需要传递第一个参数到myprop
,因为内部名称并不重要。 如果后续的myprop
调用可以以某种方式相互通信,它可以自动决定一个很长的内部属性名称。 我相信有办法实现这一点,但我不知道他们是否值得。