标签: magic-methods

如何在__call中使用is_callable?

我使用PHP 5.3,它引入了闭包.因为我现在在我的应用程序(和框架)中都有可用的闭包,所以我使用is_callable来查看是什么类型的处理程序$callback.

如果$callback is_callable,我足够了解并使用该函数/方法/闭包.如果它不可调用并且它是一个字符串,那么它可能是$this类中方法的名称.它可能存在,也可能不存在.如果我让它升级到PHP,它将"抛出"一个很好的致命错误(我喜欢那些).

但我想使用mix-ins,这意味着我需要魔术方法__call.__call非常酷,因为它(可以)在实际函数调用之前包含(s)逻辑.但是 ......如果在__call被叫方法不存在之后会发生什么?当然,我可以抛出一个例外,但直到之后我们才会知道.

问题现在是有用的is_callable,因为在实现之后__call,一切都将返回true,因为一切都有回退(存在__call).

有没有办法同时拥有:动态方法和有用的方法is_callable

我希望看到的是某种可缓存的魔术方法__is_callable,PHP将在is_callable(array($object, $method))调用时"咨询" .

在php.net上,我找不到任何像我这样对此感到愚蠢的人.这不可能!如果你使用__call,你就不is_callable能再使用了!?

我有意义吗?

PS.我已经研究过了,method_exists但这还不够好(即使我可以过滤掉所有的闭包和全局函数),因为它将为私有和受保护的方法以及公共方法返回true.

编辑
我制作了一个'更好'的is_callable来检查混音,但我认为它非常昂贵.

php overriding overloading call magic-methods

10
推荐指数
1
解决办法
3421
查看次数

哪种特殊方法在Python中绕过__getattribute__?

除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过__getattribute__()对象的元类的方法.

文档提到了特殊方法,例如__hash__,__repr____len__,我从经验中知道它也包括__iter__Python 2.7.

引用相关问题的答案:

"魔术__methods__()被特别对待:它们被内部分配到类型数据结构中的"插槽"以加速他们的查找,并且只在这些插槽中查找."

为了改善我对另一个问题的回答,我需要知道:具体来说,我们在谈论哪些方法?

python magic-methods

10
推荐指数
1
解决办法
1450
查看次数

内置魔术变量名称/属性

背景:对于那些不熟悉它的人, Sublime Text(和TextMate)通过由.tmLanguage语言定义文件定义的范围提供语法高亮和其他功能,基本上是一组用于识别给定语言中各种结构的正则表达式,例如函数定义,各种类型的字符串,保留字等

我是Python改进包的维护者(如果你感兴趣,可以通过Package Control获得),它旨在成为Python的更好的语言定义.如果需要,您可以在GitHub上阅读它,但其中一个关键特性是它实际上是维护的,这与许多未经过多年更改或更新的Sublime语言不同.

问题:我最近一直关注双重强调的__magic__东西,在找到Rafe Kettler关于魔术函数的优秀论文之后,我能够扩展语言定义的那一部分.但是,我找到一个很好的内置魔术变量名称或魔术属性列表,比如__class__或者运气少了__doc__.我已经浏览了文档的数据模型部分,但它为我的目的留下了一些不足之处,似乎主要关注魔术方法名称.

所以我的问题是,support.variable.magic.python范围应该包含哪些内容?这是它到目前为止的定义:

\b__(all|bases|class|debug|dict|doc|file|members|metaclass|methods|module|name|slots|weakref)__\b
Run Code Online (Sandbox Code Playgroud)

我开始这个项目的原因之一就是自学了更多关于Python的知识,到目前为止我确实取得了成功,但是我有点陷入困境.

为了清楚起见,我不是在寻找一个最喜欢的场外资源(尽管如果你有一个方便的链接,我会很感激)并且我不是要开始一个自以为是的讨论.我想弄清楚的是,这个列表是否看起来是合理的,或者是否有任何明显的错误.如果你确实想要自以为是,请打开一个问题,我非常乐意与你讨论.

谢谢!

python syntax built-in magic-methods sublimetext

10
推荐指数
2
解决办法
1万
查看次数

PHP的魔术方法__call在子类上

我的情况最好用一些代码来描述:

class Foo {
    function bar () {
        echo "called Foo::bar()";
    }
}

class SubFoo extends Foo {
    function __call($func) {
        if ($func == "bar") {
            echo "intercepted bar()!";
        }
    }
}

$subFoo = new SubFoo();

// what actually happens:
$subFoo->bar();    // "called Foo:bar()"

// what would be nice:
$subFoo->bar();    // "intercepted bar()!"
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过bar()在子类中重新定义(以及所有其他相关方法)来实现这一点,但就我的目的而言,如果__call函数可以处理它们会很好.它会只是让事情很多整洁和更易于管理.

这可能在PHP?

php oop magic-methods

9
推荐指数
1
解决办法
6482
查看次数

Python相当于PHP的__call()魔术方法?

在PHP中,我可以这样做:

class MyClass
{
  function __call($name, $args)
  {
    print('you tried to call a the method named: ' . $name);
  }
}
$Obj = new MyClass();
$Obj->nonexistant_method();   // prints "you tried to call a method named: nonexistant_method"
Run Code Online (Sandbox Code Playgroud)

这对于我正在处理的项目能够用Python来做是很方便的(要解析许多讨厌的XML,将它转换为对象并且能够只调用方法会很好.

Python有相同的功能吗?

php python magic-methods

9
推荐指数
1
解决办法
3468
查看次数

为什么Python没有内置混合getattr + __getitem__?

我有接受dicts或其他对象的方法以及从这些对象中获取的"fields"的名称.如果对象是dict,则该方法用于__getitem__检索命名键,或者getattr用于检索命名属性.这在网络模板语言中非常常见.例如,在变色龙模板中,您可能具有:

<p tal:content="foo.keyname">Stuff goes here</p>
Run Code Online (Sandbox Code Playgroud)

如果你foo像dict一样传入{'keyname':'bar'},然后foo.keyname获取'keyname'键以获得'bar'.如果foo是类的实例,如:

class Foo(object):
    keyname = 'baz'
Run Code Online (Sandbox Code Playgroud)

然后foo.keynamekeyname属性中获取值.变色龙本身实现了这个功能(在chameleon.py26模块中),如下所示:

def lookup_attr(obj, key):
    try:
        return getattr(obj, key)
    except AttributeError as exc:
        try:
            get = obj.__getitem__
        except AttributeError:
            raise exc
        try:
            return get(key)
        except KeyError:
            raise exc
Run Code Online (Sandbox Code Playgroud)

我在自己的包中实现了它,如:

try:
    value = obj[attribute]
except (KeyError, TypeError):
    value = getattr(obj, attribute)
Run Code Online (Sandbox Code Playgroud)

问题是,这是一种非常常见的模式.我已经在很多模块中看到过这种方法或者与它非常类似的方法.那么为什么在语言的核心,或者至少在一个核心模块中不是这样的东西呢?如果做不到这一点,是那里怎么会以明确的方式应该写?

python magic-methods getattr

9
推荐指数
3
解决办法
2959
查看次数

使用PDO :: FETCH_CLASS和Magic方法

我有一个使用魔术方法来存储属性的类.这是一个简化的例子:

class Foo {
    protected $props;

    public function __construct(array $props = array()) {
        $this->props = $props;
    }

    public function __get($prop) {
        return $this->props[$prop];
    }

    public function __set($prop, $val) {
        $this->props[$prop] = $val;
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试为PDOStatement它的每个数据库行实例化此类的对象,就像这样(不起作用):

$st->setFetchMode(PDO::FETCH_CLASS, 'Foo');

foreach ($st as $row) {
    var_dump($row);
}
Run Code Online (Sandbox Code Playgroud)

问题是,在设置属性值时,我的类PDO::FETCH_CLASS似乎没有触发魔术__set()方法.

如何使用PDO实现所需效果?

php pdo magic-methods

9
推荐指数
1
解决办法
6289
查看次数

为什么在隐式__getitem __-调用时没有调用__getattribute__?

在尝试包装任意对象时,我遇到了字典和列表的问题.调查,我设法提出了一段简单的代码,其行为我根本不理解.我希望你们中的一些人可以告诉我发生了什么:

>>> class Cl(object): # simple class that prints (and suppresses) each attribute lookup
...   def __getattribute__(self, name):
...     print 'Access:', name
... 
>>> i = Cl() # instance of class
>>> i.test # test that __getattribute__ override works
Access: test
>>> i.__getitem__ # test that it works for special functions, too
Access: __getitem__
>>> i['foo'] # but why doesn't this work?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'Cl' object has no attribute '__getitem__'
Run Code Online (Sandbox Code Playgroud)

python magic-methods

9
推荐指数
1
解决办法
620
查看次数

增加"__toString"

我不确定标题应该是什么,但代码应该更好地解释它:

class Group {
    private $number = 20;

    public function __toString() {
        return "$this->number";
    }
}

$number = new Group();
echo $number, PHP_EOL;
echo ++ $number, PHP_EOL;

echo PHP_EOL;

$number = "20";
echo $number, PHP_EOL;
echo ++ $number, PHP_EOL;

echo PHP_EOL;

$number = 20;
echo $number, PHP_EOL;
echo ++ $number, PHP_EOL;
Run Code Online (Sandbox Code Playgroud)

输出:

20
20              <--- Expected 21

20
21

20
21
Run Code Online (Sandbox Code Playgroud)

知道我为什么20而不是21?即使这样,下面的代码也适用:

$i = null ;
echo ++$i ; // output 1
Run Code Online (Sandbox Code Playgroud)

我知道Group是一个实现的对象__toString …

php increment magic-methods

9
推荐指数
2
解决办法
402
查看次数

如何在PHP中使用codesniffer检测对象上的动态声明字段

在重构之后,我们在其中一个类中有类似的东西:

class FooBar
{
    // $foo was $bla before
    private $foo;

    public function setBlubbOnArrayOnlyOnce($value)
    {
        // $this->bla was forgotten during refactoring. Must be $this->foo
        if(!isset($this->bla['blubb'])) {
             $this->foo['blubb'] = $value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以最后$ this-> foo ['blubb']总是被设定,不仅一次.这是因为PHP的神奇方法.我们不希望它可以动态访问字段,所以我想我只是添加了一个代码不一致的规则.但我没有发现任何问题,并问我原因.

PHPStorm显示了一个动态通知的字段,但我想在部署周期中使用代码(或类似的东西)自动失败.

有人对此有所了解吗?有一个很好的规则吗?我应该写自己的,怎么样?或者禁用它是不好的做法?

免责声明:我们使用测试,但有时你会错过一些东西......首先要防止这种情况.另外,请不要想出覆盖魔法的方法.我不想在每个班级都有任何特质/抽象.

php codesniffer magic-methods getter-setter phpcodesniffer

8
推荐指数
1
解决办法
558
查看次数