Python 对象属性 - 访问方法

2024-05-03

假设我有一个具有某些属性的类。 (在 Pythonic-OOP 中)如何访问这些属性是最好的?就像obj.attr?或者也许编写 get 访问器? 此类事物可接受的命名风格是什么?

Edit:您能否详细说明使用单下划线或双前导下划线命名属性的最佳实践?我发现在大多数模块中都使用了一个下划线。


如果这个问题已经被问过(我有预感,尽管搜索没有带来结果),请指出它 - 我将关闭这个问题。


关于单下划线和双下划线:两者都表示相同的“隐私”概念。也就是说,人们会知道该属性(无论是方法还是“普通”数据属性或其他任何内容)不是对象的公共 API 的一部分。人们就会知道,直接触碰它就会招来灾难。

最重要的是,双前导下划线属性(但不是单前导下划线属性)是名称损坏的以便访问它们意外地来自子类或当前类之外的任何其他地方的可能性较小。您仍然可以访问它们,但不再那么简单。例如:

>>> class ClassA:
...     def __init__(self):
...         self._single = "Single"
...         self.__double = "Double"
...     def getSingle(self):
...         return self._single
...     def getDouble(self):
...         return self.__double
... 
>>> class ClassB(ClassA):
...     def getSingle_B(self):
...         return self._single
...     def getDouble_B(self):
...         return self.__double
... 
>>> a = ClassA()
>>> b = ClassB()

您现在可以轻松访问a._single and b._single并得到_single属性创建者ClassA:

>>> a._single, b._single
('Single', 'Single')
>>> a.getSingle(), b.getSingle(), b.getSingle_B()
('Single', 'Single', 'Single')

但试图访问__double属性上的a or b直接实例将不起作用:

>>> a.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassA instance has no attribute '__double'
>>> b.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassB instance has no attribute '__double'

尽管方法定义在ClassA可以直接获取它(在任一实例上调用时):

>>> a.getDouble(), b.getDouble()
('Double', 'Double')

方法定义于ClassB不能:

>>> b.getDouble_B()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in getDouble_B
AttributeError: ClassB instance has no attribute '_ClassB__double'

就在该错误中,您会得到有关正在发生的事情的提示。这__double当在类内部访问属性名称时,属性名称将被名称修改以包含正在访问的类的名称in. When ClassA尝试访问self.__double,它实际上在编译时变成了对self._ClassA__double,同样对于ClassB。 (如果方法在ClassB被分配给__double,为了简洁起见,未包含在代码中,因此不会触及ClassA's __double但创建一个新属性。)该属性没有其他保护,因此如果您知道正确的名称,您仍然可以直接访问它:

>>> a._ClassA__double, b._ClassA__double
('Double', 'Double')

那么为什么这是一个问题呢?

好吧,每当您想要继承和更改处理此属性的任何代码的行为时,这都是一个问题。您要么必须重新实现直接触及此双下划线属性的所有内容,要么必须猜测类名并手动修改名称。当这个双下划线属性实际上是一个方法时,问题会变得更糟:重写该方法或者调用子类中的方法意味着手动进行名称修改,或者重新实现调用该方法的所有代码以不使用双下划线名称。更不用说动态访问属性了getattr():你也必须手动破坏那里。

另一方面,由于该属性仅被简单地重写,因此它仅提供表面的“保护”。任何代码片段仍然可以通过手动修改来获取该属性,尽管这会使their代码取决于名称your类,而您重构代码或重命名类(同时仍然保持相同的用户可见名称,这是 Python 中的常见做法)的努力将不必要地破坏他们的代码。他们还可以通过将他们的类命名为与你的类相同的名称来“欺骗”Python 来为他们进行名称修改:请注意,修改后的属性名称中没有包含模块名称。最后,双下划线属性在所有属性列表和所有形式的内省中仍然可见,这些内省不注意跳过以 ( 开头的属性single) 下划线。

So, if您使用双下划线名称,并且非常谨慎地使用它们,因为它们可能会变得非常不方便,并且永远不要将它们用于方法或子类可能想要重新实现、覆盖或直接访问的任何其他内容。并意识到双前导下划线名称修改提供了没有真正的保护。最后,使用一个前导下划线会给你带来同样多的好处,并给你带来更少的(潜在的、未来的)痛苦。使用单个前导下划线。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 对象属性 - 访问方法 的相关文章

随机推荐

  • spring 调度一个具有固定延迟和初始延迟的作业

    我正在尝试安排方法调用 我想在服务器启动后立即安排此方法调用 然后每 30 秒调用一次 下面的代码 Configuration EnableScheduling EnableTransactionManagement public clas
  • 如何使用IIS压缩所有文件

    IIS compression has been enabled 以下是web config的http压缩标签
  • Symfony 2 登录后重定向

    在 Symfony 2 中 您可以设置注销目标 以便注销后您将被重定向到 main 但是 登录后您将被重定向到 有没有办法为 成功 登录设置目标 firewalls dev pattern profiler wdt css images j
  • 如何在数据流中正确使用“展平”

    我们的管道如下所示 GCS gz 压缩文件 gt ParDo gt BigQuery 我想使用 展平 从 GCS 中提取多个文件作为管道的输入 但它一直因错误而烦恼 Workflow failed Causes 5001e5764f46ac
  • Rails 形式的当前日期

    我正在学习 Rails 并在书外进行一些探索 并随着知识的增长创建一个具有附加功能的简单应用程序 我正在编写一个简单的博客应用程序 我在表单中添加了一个名为 日期 的字段 我不希望这是一个字段 我希望它从服务器获取日期并将其自动放入数据库中
  • iPhone - 让 VoiceOver 宣布标签文本更改

    如果标签上的文本发生更改 是否可以使用 iPhone 上的 VoiceOver 来宣布更新后的文本 这类似于 ARIA 中的实时区域 Thanks 您可以使用 VoiceOver 朗读您喜欢的任何文本 UIAccessibilityPost
  • 如何保存我更改的网格中的行

    我使用 ng resource 从服务器获取数据 然后将数据放入表格网格中 如下所示 div div
  • JObject ToString 与 StringEnumConverter 不起作用

    我正在尝试序列化一个匿名类 如下所示 public enum ErrorCode A B C var response JObject FromObject new Error new Message Test Code ErrorCode
  • 无法更改 Visual Studio 2013 中的字体

    我曾经可以通过以下方式更改 Visual Studio 2013 的字体和颜色Tools gt Options then Environment gt Fonts and Colors 最后显示文本编辑器的设置 但是 现在我无法显示文本编辑
  • 使用 Tiny Scrollbar 自动滚动到 div 底部

    我正在编写一个shoutbox 并使其尽可能用户友好 它使用微型滚动条插件 http plugins jquery com project tinyscrollbar对于 jQuery 我想合并一个额外的函数 让我可以让它到达底部div 它
  • 如何仅使用 Javascript 减慢平滑滚动的默认速度?

    我的目标是按回车键 然后让网站滚动到底部 我已将滚动行为设置为平滑 一切都正常工作 除了平滑滚动的默认速度太快了 我怎样才能减慢它的速度 下面是我的代码 请不要使用jquery 谢谢你 document body onkeyup funct
  • 我可以通过索引访问 Parquet 文件而不将整个文件读入内存吗?

    我刚刚读到 HDF5 允许您访问数据查找 而无需将整个文件读入内存 这种寻找行为在没有 Java 的 Parquet 文件中是否可能 非 pyspark 解决方案 我使用 Parquet 是因为它有强大的 dtype 支持 import h
  • 类型错误:req.logIn 不是函数 - Passport JS

    我很确定这不是一个错误 因为谷歌搜索没有发现任何结果 我正在使用 Passport JS 和本地策略 在我的登录路线上 我使用自定义回调 并在确定用户存在后调用 req login 因为文档显示 请注意 当使用自定义 回调 应用程序有责任建
  • 如何在外部浏览器中打开 Android 应用程序中的链接?

    任何人都可以帮助我在代码中打开外部浏览器或其他 Android 应用程序中的链接吗 现在的情况是链接在应用程序本身中打开 但如果该链接属于 Android 应用程序 则无法打开 它显示安装 Android 应用程序 所以我希望如果链接可以在
  • 如何设置属性选择器的值 Expression>

    我需要使用模式工厂的想法将 Person 类实体中的实体属性 Address 与 FactoryEntities 类中的表达式 linq 相关联 看看这就是我所拥有的并且我想要做的 Address address new Address a
  • 获取发送 cURL 请求的用户的 IP 地址

    我想获取使用 php 中的 cURL POST 方法向我的服务器发送请求的用户的 IP 地址 我正在开发一个 Flight API 我将使用 cURL POST 方法获取请求 我必须获取客户端的 IP 地址并验证他的 IP 地址是否可用 如
  • Inno Setup:如何在选中的复选框上显示(隐藏/取消隐藏)密码

    我在输入查询页面中添加了一个复选框 以便在选中时使用它向我显示未发现的密码 但我不知道该怎么做 我已经创建了以下过程 但这个过程并没有改变我添加输入时的 true false 值 此过程添加了我完成这项工作的新文本框 请你帮助我好吗 pro
  • 社交登录重复帐户冲突

    我正在制作一个新应用程序 除了常规电子邮件 密码注册之外 还需要多个社交注册 但是有一种特殊情况可能会导致数据完整性问题 例子 用户在 Facebook 上注册 但没有收到任何电子邮件回复 我在数据库中创建一个用户 将电子邮件和密码设置为
  • 在 WinForms 中显示输入对话框

    我想在我的 WinForm 应用程序中显示输入模式 我浏览过网络 但没有找到执行此操作的良好模式 我知道我必须创建另一个表单 并使用 ShowDialog 方法 你是对的 请注意 模式对话框在关闭时不会自动处理 与非模式对话框不同 因此您需
  • Python 对象属性 - 访问方法

    假设我有一个具有某些属性的类 在 Pythonic OOP 中 如何访问这些属性是最好的 就像obj attr 或者也许编写 get 访问器 此类事物可接受的命名风格是什么 Edit 您能否详细说明使用单下划线或双前导下划线命名属性的最佳实