我只有 Java 方面的 OOP 编程经验,并且刚刚开始使用 Python 开发一个项目,我开始意识到 Python 让我对一些对我来说很直观的事情产生怀疑。所以我有几个关于 Python 中的 OOP 的问题。
场景:我正在编写一个发送电子邮件的程序。对于电子邮件,to
、from
、text
和 subject
字段将是必需的,其他字段如 cc
和 bcc
是可选的。此外,将有一堆实现核心邮件功能的类,因此它们将从基类 (Mailer
) 派生。
以下是我不完整的代码片段:
class Mailer(object):
__metaclass__ == abc.ABCMeta
def __init__(self,key):
self.key = key
@abc.abstractmethod
def send_email(self, mailReq):
pass
class MailGunMailer(Mailer):
def __init__(self,key):
super(MailGunMailer, self).__init__(key)
def send_email(self, mailReq):
from = mailReq.from
to = mailReq.to
subject= mailReq.subject
text = mailReq.text
options = getattr(mailReq,'options',None)
if(options != None):
if MailRequestOptions.BCC in options:
#use this property
pass
if MailRequestOptions.CC in options:
#use this property
pass
class MailRequest():
def __init__(self,from,to,subject,text):
self.from = from
self.to = to
self.subject = subject
self.text = text
def set_options(self,options):
self.options = options
class MailRequestOptions():
BCC = "bcc"
CC = "cc"
问题:
send_mail
方法可以接受多个参数(from, to, subject, text, cc, bcc
等),其中只有四个是真正的在我的应用程序中需要。由于该方法的参数数量太多,我决定创建一个名为MailRequest
的包装对象,它将四个必要的参数作为属性,所有其他参数都可以在中定义>选项
字典。问题是,在这里,只看代码就没有办法说options
是。它是dict
还是list
?此外,查看send_email
方法,也无法判断mailReq
是什么。 这是糟糕的编程习惯吗?我应该做点别的吗?来自 Java 世界,编写代码时,您无法仅通过查看代码就知道参数是什么,这让我感到非常不舒服。我了解了 Python 中的注释,但我不想使用它们,因为它们仅在更高版本中受支持。由于
options
字典应该用于指定许多其他属性(cc
和bcc
只是其中的两个),我创建了一个名为MailRequestOptions
的新类,其中包含所有可能在选项字典中指定为MailRequestOptions
静态字符串的选项。 这也是不好的做法吗,还是有更好的方法来做到这一点?我知道,这并不是 Python 特有的。
最佳答案
Python 是一个 "duck-typed"语言;如果它走路像鸭子,叫起来像鸭子,那它就是鸭子!或者,在实现方面,如果作为 mailReq
传递的对象具有 from
、to
、subject
和 text
属性,它并不重要它是否是一个 MailRequest
。
如果你想记录接口(interface)(这当然是个好主意),通常使用 docstrings这样做。我喜欢the Google style ,它可以与 sphinx-napoleon
一起使用来自动生成人类可读的文档,但其他的也可用。
def send_email(self, mailReq):
"""Send an email.
Args:
mailReq (MailRequest): the configuration for the email.
"""
...
关于你的第二个问题;将大量参数包装到容器对象中是一个 pretty common pattern .在 Python 中,您可以选择使用 "**kwargs
magic"(参见例如 What does ** (double star) and * (star) do for parameters? )使事情变得更简单:
def send_email(self, from_, to, subject, text, **config):
...
bcc = config.get('bcc', []) # option from config or a default
...
(注意 from
是 Python 中的关键字,所以不能是参数名)。
这具有合理自记录的优点 - 有四个必需参数,加上一些任意的附加关键字配置选项(同样,通常会在文档字符串中记录)。
关于从 Java 程序员的角度看 Python OOP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29387325/