我想知道是否有一种方法可以模仿 Node.js 中 PHP 的神奇方法 __get() 和 __set()。从这个问题:JavaScript getter for allproperty我知道你可以在Rhino中做到这一点,但Node是建立在V8之上的。V8有办法做到这一点吗?
我不喜欢为实体类上的每个属性使用“愚蠢”的 getter 和 setter,因此我正在考虑使用魔术方法来获取/设置这些属性,而不是创建每个单独的 getter 和 setter。这个想法是当其逻辑与典型的“return $name”或“$this->name=$name”不同时创建特定的 getter 或 setter。此外,这个神奇的方法将在不同的类上创建,并且每个实体都会扩展它(我没有对这一步考虑太多)
无论如何,您对用魔术方法替换 getter/setter 有何看法?它会对性能造成太多惩罚吗?还有其他我没有考虑到的问题吗?
我目前正在实现一个可以处理与物理单位相关的数字数据的类。
我想实现一种计算实例平方根的方法。假设您有一个具有属性值和名称的类实例:
from math import sqrt
class Foo:
def __init__(self, value, name)
self.value = value
self.name = name
def __sqrt__(self):
return sqrt(self.value)
Run Code Online (Sandbox Code Playgroud)
我想实现一个类似于add (self, other) 等魔术方法的函数,当我调用 math.sqrt() 函数时,它会计算平方根:
A = Foo(4, "meter")
root = math.sqrt(A)
Run Code Online (Sandbox Code Playgroud)
应该返回调用A.sqrt ( )函数。
我正在用 PHP 设置一个应用程序,试图遵循 Laravel 中规定的一些约定,我可以看到有很多参考资料$this->app["some_var"];
但在我的应用程序中,它抛出一个错误,提示“无法将对象用作数组”。
我知道 Laravel 使用了诸如__get()和__set()
之类的魔法方法,但我仍然得到相同的结果。
我在 App 对象的父类中使用的神奇 getter 和 setter 代码
/**
* Dynamically access container services.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
return $this[$key];
}
/**
* Dynamically set container services.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function __set($key, $value)
{
$this[$key] = $value;
}
Run Code Online (Sandbox Code Playgroud)
预期结果是它可以访问对象上不可访问的任何属性?
目前抛出一个Fatal error: Uncaught Error: Cannot use object …
我在做一个项目时遇到了一个有趣的情况:
我正在构造一个类,我们可以调用它,ValueContainer它总是在属性下存储单个值value。具有自定义ValueContainer功能,保留其他元数据等,但是我想继承所有 magic/dunder 方法(例如__add__,,,)。显而易见的解决方案是手动实现所有魔术方法并将操作指向属性。__sub____repr__valuevalue
定义示例:
class ValueContainer:
def __init__(self, value):
self.value = value
def __add__(self, other):
if isinstance(other, ValueContainer):
other = other.value
return self.value.__add__(other)
Run Code Online (Sandbox Code Playgroud)
行为示例:
vc1 = ValueContainer(1)
assert vc1 + 2 == 3
vc2 = ValueContainer(2)
assert vc1 + vc2 == 3
Run Code Online (Sandbox Code Playgroud)
然而,这里有两个问题。
type(self.value),这最终可能是 20 多个不同的函数,所有函数都具有相同的核心功能(调用 的super魔术方法value)。这让我浑身颤抖,大喊“干!干!干!”value可以是任何类型。至少我需要至少支持数字类型(, )和字符串。魔法方法集及其对数字和字符串的行为已经足够不同,使得这种情况难以处理。现在,当添加我希望能够在 中存储自定义类型的事实时,手动实现变得有点难以想象。intfloatvalue考虑到这两件事,我花了很长时间尝试不同的方法来使其发挥作用。困难的部分来自以下事实:dunder …
以下代码按排序顺序列出了名为“A”的类的属性:-
>>> class A():
def __init__(self, i):
self.at = i
>>> sorted(vars(A))
['__dict__', '__doc__', '__init__', '__module__', '__weakref__']
Run Code Online (Sandbox Code Playgroud)
现在,打印键的值,'__dict__'结果如下:-
>>> vars(A)['__dict__'] #Value of '__dict__'
<attribute '__dict__' of 'A' objects>
Run Code Online (Sandbox Code Playgroud)
根据文档, vars([object])
返回具有
__dict__属性的模块、类、实例或任何其他对象的__dict__属性。
我不明白的是,'__dict__'列表中的属性是用于vars()返回属性的相同属性,A还是具有其他目标的不同属性,例如按照建议(根据我的说法)实现 A 的对象命名空间的值其中成立。'__dict__'
编辑:-
问题的第一部分与另一个问题(也由@eliotness 提到)非常相关,但这是第二部分(如下所述),我找不到任何答案或相关问题,因此,更改标题题。
让我们考虑另一个在 Python 中生成最终基类属性列表的代码object:-
>>> sorted(vars(object))
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', ...., '__str__', '__subclasshook__']
>>> hasattr(object, '__dict__')
True …Run Code Online (Sandbox Code Playgroud) 我希望能够迭代类型而不实例化它,类似于枚举。
class Foo:
"""Class I want to iterate over without instantiating."""
ALLOWED_VALUES = (1, 2, 3)
# I want iterating over `Foo` to be equivalent to iterating over `Foo.ALLOWED_VALUES`
for val_from_tuple, val_from_foo in zip(Foo.ALLOWED_VALUES, Foo):
assert val_from_tuple == val_from_foo
Run Code Online (Sandbox Code Playgroud)
这种行为对于枚举来说是可能的,但前提是ALLOWED_VALUES有效的 python 名称。我希望在没有此限制的情况下具有相同的迭代行为。
我尝试将其实现__iter__()为staticmethodon ,这样就不需要使用Foo的实例来获取它。这允许我迭代,但会引发错误。这似乎是因为在 上查找方法,而不是在(因为是一个对象)上查找方法。FooIteratorFoo.__iter__()iter(Foo)iter(Foo)__iter__typeFooFootype
class Foo:
"""Class I want to iterate over without instantiating."""
ALLOWED_VALUES = (1, 2, 3) …Run Code Online (Sandbox Code Playgroud) 我正在编写一个项目,提供有关变量名称的建议,并且我希望它能够判断名称是否与任何保留的标识符类匹配。第一个(“private”)非常简单,只是name.startswith('_'),但 dunder 和类私有名称更复杂。有没有内置函数可以告诉我?如果不是,Python 使用的内部规则是什么?
对于 dunder,检查name.startswith('__') and name.endswith('__')不起作用,因为它会匹配'__'。也许像这样的正则表达式^__\w+__$会起作用?
对于类私有,name.startswith('__')不起作用,因为 dunder 名称不会被破坏,也不会像 那样只包含下划线的名称'___'。所以看来我必须检查名称是否以两个下划线开头,不以两个下划线结尾,并且至少包含一个非下划线字符。是对的吗?在代码中:
name.startswith('__') and not name.endswith('__') and any(c != '_' for c in name)
Run Code Online (Sandbox Code Playgroud)
我最关心的是边缘情况,所以我想确保我的规则 100% 正确。我读过对象名称之前的单下划线和双下划线的含义是什么?但细节还不够。
我定义了一个类,它的__ge__方法返回自身的一个实例,并且__bool__不允许调用其方法(类似于 Pandas Series)。
为什么X.__bool__在 during 中被调用np.int8(0) <= x,而不是在其他任何示例中被调用?谁在调用它?我已经阅读了数据模型文档,但我还没有在那里找到答案。
import numpy as np
import pandas as pd
class X:
def __bool__(self):
print(f"{self}.__bool__")
assert False
def __ge__(self, other):
print(f"{self}.__ge__")
return X()
x = X()
np.int8(0) <= x
# Console output:
# <__main__.X object at 0x000001BAC70D5C70>.__ge__
# <__main__.X object at 0x000001BAC70D5D90>.__bool__
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "<stdin>", line 4, in __bool__ …Run Code Online (Sandbox Code Playgroud) 参考Python文档__class_getitem__:
\n\n一个类通常只有在定义了特殊的类方法时才可以被参数化
\n__class_getitem__()。
并输入:
\n\n\n自 3.9 版起已弃用:
\nbuiltins.type现在支持[]. 请参阅PEP 585和通用别名类型。
这意味着在3.9版本之后,我们可以使用type[class]代替typing.Type[class],但是在pycharm中,当我使用前者时,IDE告诉我:
\n\n类
\ntypeundefined__getitem__,因此,[]不能在其实例上使用该运算符。
我在交互式 Python 中证实了这一点:
\nPython 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32\nType "help", "copyright", "credits" or "license" for more information.\n>>> list[int]\nlist[int]\n>>> list.__class_getitem__(int)\nlist[int]\n>>> type[int]\ntype[int]\n>>> type.__class_getitem__(int)\nTraceback (most recent …Run Code Online (Sandbox Code Playgroud) magic-methods ×10
python ×7
php ×3
class ×1
dictionary ×1
identifier ×1
inheritance ×1
iterator ×1
javascript ×1
laravel ×1
laravel-5 ×1
metaclass ×1
node.js ×1
numpy ×1
pandas ×1
symfony ×1
typing ×1
v8 ×1