Yan*_*ani 23 python coding-style decorator factory-method class-method
这是一个关于使用python从不同形式的相同数据创建类或类型的实例的最佳实践的问题.使用类方法是否更好,或者更好地完全使用单独的函数?假设我有一个用于描述文档大小的类.(注意:这只是一个例子.我想知道创建类实例的最佳方法,而不是描述文档大小的最佳方法.)
class Size(object):
"""
Utility object used to describe the size of a document.
"""
BYTE = 8
KILO = 1024
def __init__(self, bits):
self._bits = bits
@property
def bits(self):
return float(self._bits)
@property
def bytes(self):
return self.bits / self.BYTE
@property
def kilobits(self):
return self.bits / self.KILO
@property
def kilobytes(self):
return self.bytes / self.KILO
@property
def megabits(self):
return self.kilobits / self.KILO
@property
def megabytes(self):
return self.kilobytes / self.KILO
Run Code Online (Sandbox Code Playgroud)
我的__init__
方法采用以位表示的大小值(位和唯一的位,我想保持这种方式),但是假设我有一个以字节为单位的大小值,我想创建一个类的实例.使用类方法是否更好,或者更好地完全使用单独的函数?
class Size(object):
"""
Utility object used to describe the size of a document.
"""
BYTE = 8
KILO = 1024
@classmethod
def from_bytes(cls, bytes):
bits = bytes * cls.BYTE
return cls(bits)
Run Code Online (Sandbox Code Playgroud)
要么
def create_instance_from_bytes(bytes):
bits = bytes * Size.BYTE
return Size(bits)
Run Code Online (Sandbox Code Playgroud)
这可能看起来不是一个问题,也许两个例子都是有效的,但每当我需要实现这样的事情时,我都会考虑它.很长一段时间,我更喜欢类方法方法,因为我喜欢将类和工厂方法绑在一起的组织好处.此外,使用类方法保留了创建任何子类的实例的能力,因此它更加面向对象.另一方面,一位朋友曾经说过"当有疑问时,做标准库所做的事情",我还没有在标准库中找到这样的例子.
aba*_*ert 27
首先,大多数时候你认为你需要这样的东西,你没有; 这表明你正在尝试像Java一样对待Python,解决方案就是退后一步,问你为什么需要工厂.
通常,最简单的方法是使用带有默认/可选/关键字参数的构造函数.即使你在Java中从未用这种方式编写的情况 - 即使在C++或ObjC中重载构造函数会出错的情况 - 在Python中看起来也很自然.例如,size = Size(bytes=20)
或者size = Size(20, Size.BYTES)
看起来合理.就此而言,一个Bytes(20)
继承Size
并且绝对只添加__init__
过载的类看起来是合理的.这些是微不足道的定义:
def __init__(self, *, bits=None, bytes=None, kilobits=None, kilobytes=None):
Run Code Online (Sandbox Code Playgroud)
要么:
BITS, BYTES, KILOBITS, KILOBYTES = 1, 8, 1024, 8192 # or object(), object(), object(), object()
def __init__(self, count, unit=Size.BITS):
Run Code Online (Sandbox Code Playgroud)
但是,有时你确实需要工厂功能.那么,那你做什么?嗯,有两种常常被混为"工厂"的东西.
阿@classmethod
是做一个"交替构造函数" -there是示例遍布stdlib-惯用方式itertools.chain.from_iterable
,datetime.datetime.fromordinal
等等.
一个函数是做"我不关心实际类是什么"工厂的惯用方法.看一下,例如,内置open
功能.你知道它在3.3中的回报吗?你关心?不.这就是为什么它是一个功能,而不是io.TextIOWrapper.open
什么.
您给出的示例似乎是一个完全合法的用例,非常清楚地适用于"备用构造函数"bin(如果它不适合"带有额外参数的构造函数"bin).
归档时间: |
|
查看次数: |
18067 次 |
最近记录: |