温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Python中的面向对象是否没有意义

发布时间:2021-10-09 17:18:42 来源:亿速云 阅读:133 作者:柒染 栏目:编程语言

Python中的面向对象是否没有意义,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

近来,许多人都在抨击面向对象,虽然我不认为面向对象本身有什么问题,但我觉得至少在 Python 中没这个必要。

1、没有必要使用面向对象

举个例子,比如下面的代码完全没有必要使用面向对象。

class ApiClient:     def __init__(self, root_url: str, session_cls: sessionmaker):         self.root_url = root_url         self.session_cls = session_cls     def construct_url(self, entity: str) -> str:         returnf"{self.root_url}/v1/{entity}"     def get_items(self,entity: str) -> List[Item]:         resp = requests.get(self.construct_url(entity))         resp.raise_for_status()         return [Item(**n) for n in resp.json()["items"]]     def save_items(self, entity: str) -> None:         with scoped_session(self.session_cls)as session:              session.add(self.get_items(entity))   class ClientA(ApiClient):     def construct_url(self, entity: str) -> str:         returnf"{self.root_url}/{entity}"   class ClientB(ApiClient):     def construct_url(self, entity: str) -> str:         returnf"{self.root_url}/a/special/place/{entity}"  client_a = ClientA("https://client-a",session_cls)  client_a.save_items("bars")

这里使用了面向对象,因为我们想把 root_url 绑定到某个对象上,而且不想每次都传递 sessionmaker。我们还想使用继承,在调用的中途访问一个方法。

但如果只通过数据传递和函数能实现吗?

@dataclass  class Client:     root_url: str     url_layout: str  client_a = Client(     root_url="https://client-a",     url_layout="{root_url}/{entity}",  )  client_b = Client(     root_url="https://client-b",     url_layout="{root_url}/a/special/place/{entity}",  )  def construct_url(client: Client, entity: str) -> str:     returnclient.url_layout.format(root_url=client.root_url, entityentity=entity)  def get_items(client: Client, entity: str) -> List[Item]:     resp = requests.get(construct_url(client, entity))     resp.raise_for_status()     return [Item(**n) for n in resp.json()["items"]]  def save_items(client: Client, session_cls: session_cls, entity: str) -> None:     withscoped_session(session_cls) as session:         session.add(get_items(client, entity))  save_items(client_a,session_cls, "bars")

我们必须随时传递 Client 和 session_cls。

但有什么关系呢?代码量甚至还少了 10%。这样编写的代码很容易理解,而且不需要使用面向对象。

有人管这种写法叫做“函数袋”。就是说,整个代码都由有类型的数据和一大堆模块作用域的函数组成。

那么全局变量怎么处理?你可以参考这篇文章(https://leontrolski.github.io/sane-config.html),在整个应用程序的生命周期内重用 config 或 db 的 session,

接口、抽象类怎么办?实际上你不需要它们,直接写代码就行了。平心而论,Python 有了类型标注之后,函数袋风格才开始发挥真正的魅力。

不纯粹的函数怎么办?

如果你想采用纯粹的函数式编程,你可能想编写纯粹的类,然后使用不纯粹的“适配器”实例来做一些处理:getting-the-current-datetime/API-calls/talking-to-the-db/other-impure-stuff。这个想法很不错。实际上你可以直接使用 freezegun、responses 等方法来避免大量麻烦。

2、例外

但也有一些例外的情况:

  •  你可能注意到,重构的代码中加入了@dataclass,它们只是记录类型。Python 5 可以直接支持这些,不需要使用“常规”类。

  •  使用 Exception 的子类是没问题的。使用 try: ... except SomeClass: ...,基本上会形成一种层级,不过没关系,只要不要搞得过于复杂。

  •  Enum,与上面一样,它们非常适合 Python。

  在极罕见的情况下(至少在应用程序的开发中很少遇到),你可能会想出一种非常好用的类型然后到处使用,就像pandas.DataFrame/sqlalchemy.Session 一样。但是一般情况下,不要自欺欺人,不要骗自己说我们正在构建了不起的应用程序。谦虚使人进步。

3、面向对象的弊端

虽然在本文开头,我说过我不认为面向对象本身有什么问题,但实际上我还是觉得面向对象不仅没有帮助性,而且还常常混淆问题,鼓励一些不良做法:

  •  面向对象鼓励你修改数据。函数袋非常反对修改参数。不相信的话,你可以试试看,但可千万别生气。

  •  面向对象只是返回的全局变量。你无法在函数之间共享数据,self 会强迫你使用更小的状态空间编写方便测试的函数。

  •  混合数据和函数会加剧序列化的难度,而在当今 REST API 流行的情况下,序列化非常有用。

  •  面向对象带来了疯狂的继承体系,关于这个话题的讨论到处都是。

  •  最重要的是,面向对象没有任何附加价值,它只会导致你无法专心解决问题,并加剧浏览与理解代码的难度。 

关于Python中的面向对象是否没有意义问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI