PHP和Python对象中的静态方法,两种不同的世界...?
我是一名PHP程序员,正在尝试进入Python的世界,但对我来说这非常困难。
在PHP中,静态方法最大的好处就是可以自动创建实例。你不需要在每个文件中都声明对象,如果你只需要用一次,甚至可以用一行代码来传不同的参数。
<?php
class Foo {
function __constructor__(){
$this->var = 'blah';
}
public static function aStaticMethod() {
return $this->var;
}
}
echo Foo::aStaticMethod();
?>
我们可以从静态方法调用构造函数,对吧?而且我们可以像调用普通方法一样访问类中的所有内容……我们甚至可以在PHP类中有一个静态构造函数,并这样调用它:Object::construct()->myMethod();(这样每次都可以传不同的参数)
但在Python中就不行了吗??@staticmethod让类中的方法变成一个简单的函数,完全看不到任何东西??
class socket(object):
def __init__(self):
self.oclass = otherclass()
print 'test' # does this constructor called at all when calling static method??
@staticmethod
def ping():
return self.oclass.send('PING') # i can't access anything!!!
print Anidb.ping()
我无法从那个该死的静态方法中访问任何东西,它就像一个独立的函数,或者类似的东西……??
也许我用错了装饰器?也许Python中有类似PHP静态方法的东西?
1) 请告诉我为什么静态方法是孤立的。
2) 请告诉我如何实现和PHP静态方法相同的行为。
3) 如果PHP静态方法的行为不好,请告诉我它的替代实用用法。
附言:我希望所有这些能尽量少写代码。
附附言:对示例代码的详细注释将不胜感激。
谢谢。
3 个回答
你需要用到classmethod
。这个东西会把类本身作为第一个参数传进去。
编辑:
class C(object):
foo = 42
@classmethod
def printfoo(cls):
print cls.foo
C.printfoo()
在PHP中,静态方法并不像你想的那样,它们不能访问实例成员。也就是说,使用静态方法时不能用到$this
!
<?php
class Foo {
public static $var = 'foo ';
function __construct(){
echo 'constructing ';
$this->var = 'blah ';
}
public function aMethod() {
return $this->var;
}
public static function aStaticMethod() {
#return $this->$var; -> you can't do that,
# $this can be accessed only in instance methods, not static
return self::$var;
}
}
$foo = new Foo();
echo $foo->aMethod();
echo Foo::aStaticMethod();
?>
在Python中,对象有三种方法。静态
方法就像是在类外定义的函数,把它放在对象里只是为了和类放在一起,作为辅助函数。类
方法只能访问类中定义的变量(用@classmethod
这个装饰器来标记)。这和PHP中的静态成员或方法差不多。这样的类方法的第一个参数应该是cls
,可以通过cls
访问类的内容。普通方法的第一个参数必须是self
,只有它们能访问实例成员。
如果你想要多个相同类型的对象,肯定需要实例,其他类型的方法并不是你想要的。如果你只有一个对象的实例,可以考虑使用类方法(或者PHP的静态方法)。
不过在大多数情况下,如果你不知道为什么要这样做,就不要去折腾这些,还是用对象的实例和普通方法比较好。否则,你可能会因为引入了很多限制而让你的代码后续出现问题,这种做法叫做过早优化。
我看到你已经接受了另一个答案,但我不确定那个答案能否和你的代码一起工作。具体来说,oclass这个变量只会在类的实例中创建,而不是在类本身中。你可以这样做:
class socket(object):
oclass = otherclass()
@classmethod
def ping(cls):
return cls.oclass.send('PING')
socket.ping()
不过,如果你使用你现有的代码,并且去掉所有的装饰器,你可以简单地在同一行中创建实例并调用一个方法:
socket().ping()