为了账号安全,请及时绑定邮箱和手机立即绑定

Python类成员的困惑

Python类成员的困惑

慕少森 2021-03-23 12:09:26
首先,我来自Java和PHP背景,现在正在学习python。因此,这似乎是一个愚蠢的问题,但这使我有些困惑。以php为例:class MyClass{   private $myMember;   public function __construct($myMember = null)   {       $this->myMember = $myMember;   }   public function setMyMember($myMember)   {       $this->myMember = $myMember;   }   public function getMyMember()   {       return $this->myMember;   }}这完全是101 OOP的教科书。一个具有单个私有成员以及一个getter和setter的类。但是,学习一些python似乎并不那么简单。首先,构造函数不是真正的构造函数(但您可以在such ??上使用)其次,任何类级别的减速度都被视为静态??。因此,python中的self.myMember实际上在实例上设置了与类级别myMember不同的变量吗?最后,如果我的困惑是正确的-上面的相同示例将如何在python中编码?
查看完整描述

3 回答

?
心有法竹

TA贡献1866条经验 获得超5个赞

通常,您不会在Python中使用getter和setter;除非您需要转换值,在设置或获取过程中需要副作用,或者需要防止获取或设置,否则,只需使用属性即可:


class MyClass(object):

    def __init__(self, member):

        self.member = member

实例属性与类属性是分开的;将属性设置为onself表示您正在操作实例,类(MyClass.member)上的属性是类属性,因此在实例之间共享。这是通过在查找属性时将类用作备用方法来实现的。首先查询实例,然后查询实例的类,然后查询该类的基类;设置self.member意味着MyClass.member在实例上不再可见任何对象。


从__init__技术上讲,该方法实际上不是构造函数。被调用self时已经存在__init__。相反,它是一个初始化程序,您可以使用它设置第一个值。如果您需要一个实际的构造函数(实例工厂),则需要查找__new__静态方法。请注意,在PHP中,它__construct也是一个初始化程序,而不是构造函数!


对于确实需要创建setter和getter的那些情况,请使用propertydecorator函数:


class MyClass(object):

    def __init__(self, member):

        self._member = member


    @property

    def member(self):

        return 'Hello {}!'.format(self._member)


    @member.setter

    def member(self, value):

        # Remove "Hello " and "!" from the start and end of any value being set.

        if value.startswith('Hello '):

            value = value.split(None, 1)[1]

        self._member = value.rstrip('!')

演示:


>>> m = MyClass('World')

>>> m.member

'Hello World!'

>>> m.member = 'Hello Planet Earth!'

>>> m.member

'Hello Planet Earth!'

>>> m._member

'Planet Earth'


查看完整回答
反对 回复 2021-03-26
?
缥缈止盈

TA贡献2041条经验 获得超4个赞

这将是这样的:


class MyClass(object):


    def __init__(self, myMember=None):

        self._myMember = myMember


    @property

    def myMember(self):

        return self._myMember


    @myMember.setter

    def myMember(self, value):

        self._myMember = value

演示:


c = MyClass()

c.myMember = 10

print c.myMember

你有:


# 10


查看完整回答
反对 回复 2021-03-26
?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

在python中,类创建一个新的名称空间。除非进行有趣的交易(例如元类),否则名称空间中的内容就成为该类的属性。


class Foo(object): #inherit from object in python2.x ... It's a good idea

     class_variable = 3

     __not_really_private_but_sort_of = 7

现在,我创建了一个具有2个属性的类。第一个是“公共”。第二个是“ private”,因为它以双下划线为前缀,从而调用python的名称修饰。在python中,很少使用。毕竟,我们都是这里的程序员:)。


当您调用一个类时,它调用__new__方法(构造函数),然后(如果__new__返回该类的实例)则调用初始化器(__init__)。在大多数情况下,您无需执行任何操作__new__-默认值__new__做得很好。由于__init__是常规方法,因此它将类的实例作为第一个参数-基本是this->从其他语言来填充指针的作用:


class Foo(object):

    member = 4

    other_member = 5

    def __init__(self):

        print "__init__ called!"

        self.member = 3

        print self.member

        print self.other_member

与其他语言相比,python有点奇怪的事实是,如果实例没有成员,则python然后在类上然后在基类上查找成员(按方法解析顺序搜索)。如果在任何地方都找不到该成员,则会引发一个AttributeError。因此,如果我实例化上述类,它将打印:


__init__ called!

3

5

还要注意,我可以通过该类访问该类的成员(您称其为“静态”):


print Foo.member

或通过实例:


print Foo().__class__.member

至于您将如何用python编写上述PHP……答案是您不会。最好这样写:


class MyClass(object):

    def __init__(self,mymember=None):

        self.mymember = mymember

确实没有充分的理由要有一个以设置私人成员为唯一目的的二传手。如果您希望用户能够重置mymember属性,那么惯用的方法是让他们可以直接访问它,而不是强迫他们调用函数来完成这项工作。mymember如果您发现确实需要该功能,则可以稍后再将其设为一个属性(如其他一些答案中所述)。


查看完整回答
反对 回复 2021-03-26
  • 3 回答
  • 0 关注
  • 202 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号