在Python中将PHP的__get()与__get __()和__getattr __()进行比较

Bre*_*don 11 php python

__get__()__getattr__()Python有什么区别?我来自PHP背景,只有__get().我什么时候应该使用哪个功能?

我一直试图解决这个问题.我看到很多的问题,如这一次,问的区别__getattr__()__getattribute__(),虽然.

pha*_*t0m 8

首先也是最重要的,PHP也不能有一个等同于Python的__get__()-还差得远!你最需要的是什么__getattr__().

我来自PHP背景,只有 __get__

PHP有一个名为的魔术方法__get(),只要您尝试访问不存在的属性,就会调用该方法.

非等价物的简短列表

首先,让我们清楚一些事情:

  • PHP并没有具有同等Python的__get__()
  • PHP并没有具有同等Python的__getattr__()
  • PHP并没有具有同等Python的__getattribute__()
  • Python不具有等同于PHP的__get()

(并分别针对所有的setter方法.)

相反,阿希姆的假设,__get()不能做到像Python的__getattr__()!
Python没有区分方法和属性,但PHP确实如此,这就是PHP有第二种方法的原因:__call().

__call()每当您尝试在不存在的对象上调用方法时执行.Python没有相应的,因为一个方法只是一个可调用的对象(属性).

PHP中的一个例子:

<?php

$obj = new stdClass();
($obj->test)();
Run Code Online (Sandbox Code Playgroud)

在Python中,这将失败AttributeError.但是,在PHP中,这甚至不编译:

解析错误:语法错误,意外'('第4行

与Python比较:

obj.method()
# is eqvuivalent to:
(obj.method)()
Run Code Online (Sandbox Code Playgroud)

这是一个重要的区别.我们得出结论,PHP和Python思考调用方法的方式完全不同.

PHP的"呼叫意识"

  • PHP obj 知道你调用一个方法
    • 您可以在调用的对象上显式处理对现有方法的调用
    • 这是因为PHP的表达式模型非常不一致(PHP 5.4虽然向前迈出了一小步)
  • 但是Python的obj确实不是.

这使得对PHP有obj.does_not_exist评价到3,但obj.does_not_exist()5.

据我所知,在Python中不可能这样做.(这将允许我们将PHP的不一致性描述为一种功能.)

因此,我们将一个子弹点扩展到"不等效"列表:

  • Python不具有等同于PHP的__call()/__callStatic()

总结一下

PHP提供了两种不同的机制:

  • __get() 对于不存在的属性
  • __call() 用于调用不存在的方法

Python只有一种机制,因为它不区分属性和方法,只要它涉及它们都是属性.

  • __getattr__() 当属性不存在时调用.
  • obj.non_existing()不是特殊的"调用语法",它()是应用调用运算符的表达式:(obj.__getattr__("non_existing"))()

免责声明:__getattr__()当属性不存在时,并不总是调用.__getattribute__()在查找链中具有最高优先级,因此可能导致__getattr__()被忽略.

__get__() Python中的内容与上面提到的完全不同.

该文档描述了描述符"a descriptor is an object attribute with “binding behavior”".我可以直观地理解"绑定行为"应该是什么意思,但仅仅因为我已经理解了描述符的作用.

我会选择将描述符描述为可以在多个类之间共享的" 自我感知属性".

让我解释一下,我的意思是"自我意识".这样的属性:

  • 知道他们何时被访问或阅读
  • 知道什么时候被写入
  • 知道他们是通过读/写的
  • 知道什么时候被删除

这些属性是独立的对象:"描述符"对象,即遵循所谓的"描述符协议"的对象,它定义了一组方法以及这些对象可以实现的相应签名.

对象不拥有描述符属性.实际上,它们属于对象的对应类(或其祖先).但是,相同的描述符对象可以"属于"多个类.

:"人,他们通过阅读",究竟是指的正确方法objobj.attr?我会说:attr访问"通过" obj.


Ach*_*him 5

您可以在此处找到所有这些方法的详细文档 .

来自PHP,您应该首先熟悉Python对象模型.它比PHP更丰富,所以你不应该尝试将你的PHP知识1:1映射到Python.如果要开发PHP,请使用PHP.如果你想用Python开发,学习Python.

回到你原来的问题:__getattr__可能是与__getPHP中的函数相同的函数.__get__在Python中用于实现描述符.有关描述符的详细信息也可以在我上面提到的文档中找到.

  • 也值得一无所知,你几乎*永远不必直接访问这些方法.您可能需要覆盖它们,但是您永远不应该调用它们. (3认同)