从 Java 程序员的角度看 Python OOP

标签 python oop

我只有 Java 方面的 OOP 编程经验,并且刚刚开始使用 Python 开发一个项目,我开始意识到 Python 让我对一些对我来说很直观的事情产生怀疑。所以我有几个关于 Python 中的 OOP 的问题。

场景:我正在编写一个发送电子邮件的程序。对于电子邮件,tofromtextsubject 字段将是必需的,其他字段如 ccbcc 是可选的。此外,将有一堆实现核心邮件功能的类,因此它们将从基类 (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"

问题:

  1. send_mail 方法可以接受多个参数(from, to, subject, text, cc, bcc 等),其中只有四个是真正的在我的应用程序中需要。由于该方法的参数数量太多,我决定创建一个名为 MailRequest 的包装对象,它将四个必要的参数作为属性,所有其他参数都可以在 中定义>选项字典。问题是,在这里,只看代码就没有办法说 options 是。它是 dict 还是 list?此外,查看 send_email 方法,也无法判断 mailReq 是什么。 这是糟糕的编程习惯吗?我应该做点别的吗?来自 Java 世界,编写代码时,您无法仅通过查看代码就知道参数是什么,这让我感到非常不舒服。我了解了 Python 中的注释,但我不想使用它们,因为它们仅在更高版本中受支持。

  2. 由于 options 字典应该用于指定许多其他属性(ccbcc 只是其中的两个),我创建了一个名为 MailRequestOptions 的新类,其中包含所有可能在选项字典中指定为 MailRequestOptions 静态字符串的选项。 这也是不好的做法吗,还是有更好的方法来做到这一点?我知道,这并不是 Python 特有的。

最佳答案

Python 是一个 "duck-typed"语言;如果它走路像鸭子,叫起来像鸭子,那它就是鸭子!或者,在实现方面,如果作为 mailReq 传递的对象具有 fromtosubjecttext 属性,它并不重要它是否是一个 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/

相关文章:

python - 在numpy中生成随机数的函数之间的区别

php - 一个类的实例可以更改另一个类的实例中的变量吗?

Java - 是否应该通过 getter 和 setter 方法在构造函数中访问私有(private)实例变量?

python - 为什么 Python 不完全面向对象?

java - 不能重用方法android OOP

python - 使用 ldap python 启用 Active Directory 用户帐户

python - 使用python将十六进制写入文件

java - 如何访问私有(private)包类的公共(public)成员?

Python - argparse 需要或

python - PyQt5动态添加矩形到QML网格