是否可以测试PHP中的变量是否是静态的?我正在尝试创建一个__get也看静态变量的魔术方法.我发现property_exists()当变量也是静态时返回true.但我需要使用::而不是->我期望的?
我想知道是否有办法向变量添加类似更改侦听器的内容.我所说的最简单的例子就是沿着这些方向发挥作用;
// Start with a variable
$variable = "some value";
// Define a listener
function myChangeListener($variable) {
// encode with json_encode and send in cookie
}
// Add my listener to the variable
addListenerToVariable(&$variable, 'myChangeListener');
// Change the variables value, triggering my listener
$variable = "new value";
Run Code Online (Sandbox Code Playgroud)
现在你可能会问为什么在世界上我甚至需要打扰这种方法,为什么不只是创建一个函数来设置cookie.答案是我有一个&__get($var)魔术方法返回对多维数组元素的引用,我希望使用这样的东西来检测数组元素或其中一个子元素是否已被编辑,然后发送一个cookie,如果有的话.希望的结果会像这样起作用;
$cookies->testArray["test"] = "newValue";
// This would send the cookie 'testArray' with the value '{"test":"newValue"}'
Run Code Online (Sandbox Code Playgroud)
老实说,我认为这是完全不可能的,如果我是正确的,我道歉.但我昨天刚刚学会了如何正确使用引用,所以我想在完全注销这个想法之前我会问.
感谢我得到的任何回复,无论是我希望的还是我期望的.
编辑:
为了更加清晰,这里是我想要完成的一个示例类;
class MyCookies {
private $cookies = array();
private $cookieTag = "MyTag";
public …Run Code Online (Sandbox Code Playgroud) 我有一个类似于这个(强烈简化)示例的包装类:
class wrap(object):
def __init__(self):
self._data = range(10)
def __getitem__(self, key):
return self._data.__getitem__(key)
Run Code Online (Sandbox Code Playgroud)
我可以像这样使用它:
w = wrap()
print w[2] # yields "2"
Run Code Online (Sandbox Code Playgroud)
我以为我可以通过改变这个来优化和摆脱一个函数调用:
class wrap(object):
def __init__(self):
self._data = range(10)
self.__getitem__ = self._data.__getitem__
Run Code Online (Sandbox Code Playgroud)
但是,我收到了
TypeError:'wrap'对象不支持索引
对于print w[2]后一版本的行.
直接调用该方法,即print w.__getitem__(2)在两种情况下都有效...
为什么赋值版本不允许索引?
这里我定义了不可变类 str。在 新方法中,我将“hello”等实例的值更改为大写。当我们可以在init中定义 upper 时,为什么要使用new来实现呢?
class Upperstr(str):
def __new__(cls,value=""):
print(cls)
print(value)
return str.__new__(cls,value.upper())
# def __init__(self,m1):
# self.m1 = m1.upper()
u = Upperstr("hello")
print(u)
Run Code Online (Sandbox Code Playgroud)
New 用于创建类实例。新方法还有哪些其他用途?
例如,请考虑以下情况:
class FooMeta(type):
def __len__(cls):
return 9000
class GoodBar(metaclass=FooMeta):
def __len__(self):
return 9001
class BadBar(metaclass=FooMeta):
@classmethod
def __len__(cls):
return 9002
len(GoodBar) -> 9000
len(GoodBar()) -> 9001
GoodBar.__len__() -> TypeError (missing 1 required positional argument)
GoodBar().__len__() -> 9001
len(BadBar) -> 9000 (!!!)
len(BadBar()) -> 9002
BadBar.__len__() -> 9002
BadBar().__len__() -> 9002
Run Code Online (Sandbox Code Playgroud)
问题在于len(BadBar)返回 9000 而不是 9002,这是预期的行为。
这种行为(在某种程度上)记录在Python 数据模型 - 特殊方法查找中,但它没有提到任何有关类方法的内容,而且我并不真正理解与@classmethod装饰器的交互。
除了明显的元类解决方案(即替换/扩展FooMeta)之外,是否有一种方法可以覆盖或扩展元类函数,以便len(BadBar) -> 9002?
为了澄清,在我的特定用例中,我无法编辑元类,并且我不想对其进行子类化和/或创建我自己的元类,除非这是唯一可能的方法。
在codeigniter我试图使用这个插件,这需要我在我的模型中实现一个toString方法.我的toString方法就是这么做的
public function __toString()
{
return (string)$this->name;
}
Run Code Online (Sandbox Code Playgroud)
在我的本地机器上使用php 5.3一切正常,但是在生产服务器上使用php 5.1.6它显示"对象ID#48",其中该对象的name属性的值应该出现.....我发现了一些关于这里的问题但我还是不明白......我怎么能解决这个问题?
做了一些研究之后,我终于找到了一个问题的答案,我很快就会在这里提出这个问题; 你如何通过阵列工作__get,并__set在PHP魔术方法?每当我试图用类似的东西设置一个值$object->foo['bar'] = 42;似乎默默地丢弃它.
无论如何,答案很简单; 该__get方法只需要通过引用返回.在它前面扔了一个&符后,确实有效.
我的问题其实是,为什么?我似乎无法理解为什么这有效.如何__get通过引用返回影响__set使用多维数组?
编辑:顺便说一句,运行PHP 5.3.1
我有一个自定义序列类型。它本质上是列表加布尔标志的包装,我希望它模仿通常的不可变序列行为。
我的问题是切片。我知道在Python 3中,实现它的__getitem__(key)方法是有一个方法,如果%key一个索引是一个项目,则返回一个项目;如果%key是一个切片对象,则返回一个切片的序列。但是我应该如何区分这些情况?
我基本上有两个假设。
sliced_list = self.wrapped_list[key]
if isinstance(key, slice):
return MyCustomSequenceType(sliced_list, boolean_flag)
return sliced_list
Run Code Online (Sandbox Code Playgroud)
但这是邪恶的,不是吗?要么
sliced_list = self.wrapped_list[key]
try:
return MyCustomSequenceType(sliced_list, boolean_flag)
except TypeError:
return sliced_list
Run Code Online (Sandbox Code Playgroud)
后者看起来更pythonic。它依赖于MyCustomSequenceType.__init__(self, datas, flag)调用len(datas)的事实,因此TypeError如果%datasis是,则会引发integer。但是,如果再__init__提出TypeError另一个随机问题,那将是无法追踪的。另外,http: //wiki.cython.org/enhancements/numpy/getitem暗示了isinstance速度更快(实际上更容易被优化)。
那我该怎么办?
我有一个问题,一直在破坏我想要做的事情很长一段时间.它与在PHP中使用魔法获取和设置以及尝试对对象进行预增量有关.我有一个类如下的PHP类:
class Foo {
public $object;
function __construct() {
$this->object = array("bar" => 1);
}
function & __get($name) {
return $this->object[$name];
}
function __set($name, $value) {
echo "Old value: ". $this->object[$name] ." - New value: ". $value ."\n";
$this->object[$name] = $value;
}
}
Run Code Online (Sandbox Code Playgroud)
注意&的__get方法.现在我运行这段代码:
$o = new Foo();
echo "First test\n";
$o->bar = 2;
echo "Second test\n";
$o->bar = $o->bar + 1;
echo "Third test\n";
$o->bar += 1;
echo "Fourth test\n";
++$o->bar;
Run Code Online (Sandbox Code Playgroud)
输出是:
First test
Old …Run Code Online (Sandbox Code Playgroud) 来自https://docs.python.org/3.6/library/functions.html#getattr
Run Code Online (Sandbox Code Playgroud)getattr(object, name[, default])返回指定属性的值
object.name必须是一个字符串.如果字符串是对象属性之一的名称,则结果是该属性的值.例如,getattr(x, 'foobar')相当于x.foobar.如果named属性不存在,default则返回(如果提供),否则AttributeError引发.
如何getattr与object.__getattribute__和object.__getattr__?
不getattr打电话object.__getattribute__或object.__getattr__?我猜这个前者?
magic-methods ×10
php ×5
python ×5
built-in ×1
class ×1
indexing ×1
listener ×1
metaclass ×1
new-operator ×1
oop ×1
operators ×1
overloading ×1
overriding ×1
python-3.x ×1
reference ×1
slice ×1
tostring ×1
typechecking ×1
variables ×1
wrapper ×1