首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Python中避免显式的“self”?

如何在Python中避免显式的“self”?
EN

Stack Overflow用户
提问于 2009-12-31 13:50:07
回答 11查看 60.4K关注 0票数 148

我一直在通过学习一些pygame tutorials来学习Python。

在其中,我发现关键字self被广泛使用,并且主要来自Java背景,我发现我总是忘记键入self。例如,我会输入self.rect.centerx而不是rect,因为对我来说,rect已经是该类的成员变量了。

对于这种情况,我能想到的Java并行方法是必须在所有对成员变量的引用前面加上这个前缀。

我是不是在所有的成员变量前都加上了self前缀,或者有没有一种方法可以让我避免这样做?

即使我的建议不是pythonic式的,我仍然想知道它是否可能。

我已经看了这些相关的SO问题,但它们并没有完全回答我想要的:

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2009-12-31 13:57:30

Python需要指定self.这样做的结果是,即使没有完整的类定义,也不会混淆什么是成员,什么不是成员。这将导致有用的属性,例如:您不能添加意外地隐藏非成员的成员,从而破坏代码。

一个极端的例子:你可以编写一个类,而不知道它可能有什么基类,并且总是知道你是否正在访问一个成员:

代码语言:javascript
复制
class A(some_function()):
  def f(self):
    self.member = 42
    self.method()

这是完整的代码!(some_function返回用作基数的类型。)

另一种是动态组合类的方法:

代码语言:javascript
复制
class B(object):
  pass

print B()
# <__main__.B object at 0xb7e4082c>

def B_init(self):
  self.answer = 42
def B_str(self):
  return "<The answer is %s.>" % self.answer
# notice these functions require no knowledge of the actual class
# how hard are they to read and realize that "members" are used?

B.__init__ = B_init
B.__str__ = B_str

print B()
# <The answer is 42.>

请记住,这两个示例都是极端的,您不会每天都看到它们,我也不是建议您经常编写这样的代码,但它们确实清楚地显示了self的某些方面是显式需要的。

票数 106
EN

Stack Overflow用户

发布于 2018-03-16 02:55:21

之前的答案基本上都是“你不能”或“你不应该”的变体。虽然我同意后一种观点,但从技术上讲,这个问题仍然没有答案。

此外,有些人可能想要按照实际问题的路线做一些事情,这是有正当理由的。我有时遇到的一件事是冗长的数学方程式,使用长名称会使方程式难以辨认。这里有几种方法,你可以在一个固定的例子中做到这一点:

代码语言:javascript
复制
import numpy as np
class MyFunkyGaussian() :
    def __init__(self, A, x0, w, s, y0) :
        self.A = float(A)
        self.x0 = x0
        self.w = w
        self.y0 = y0
        self.s = s

    # The correct way, but subjectively less readable to some (like me) 
    def calc1(self, x) :
        return (self.A/(self.w*np.sqrt(np.pi))/(1+self.s*self.w**2/2)
                * np.exp( -(x-self.x0)**2/self.w**2)
                * (1+self.s*(x-self.x0)**2) + self.y0 )

    # The correct way if you really don't want to use 'self' in the calculations
    def calc2(self, x) :
        # Explicity copy variables
        A, x0, w, y0, s = self.A, self.x0, self.w, self.y0, self.s
        sqrt, exp, pi = np.sqrt, np.exp, np.pi
        return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
                * exp( -(x-x0)**2/w**2 )
                * (1+s*(x-x0)**2) + y0 )

    # Probably a bad idea...
    def calc3(self, x) :
        # Automatically copy every class vairable
        for k in self.__dict__ : exec(k+'= self.'+k)
        sqrt, exp, pi = np.sqrt, np.exp, np.pi
        return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
                * exp( -(x-x0)**2/w**2 )
                * (1+s*(x-x0)**2) + y0 )

g = MyFunkyGaussian(2.0, 1.5, 3.0, 5.0, 0.0)
print(g.calc1(0.5))
print(g.calc2(0.5))
print(g.calc3(0.5))

第三个例子--也就是说,使用for k in self.__dict__ : exec(k+'= self.'+k)基本上就是这个问题的实际要求,但我要明确的是,我认为这通常不是一个好主意。

有关更多信息,以及遍历类变量甚至函数的方法,请参阅对this question的解答和讨论。有关动态命名变量的其他方法的讨论,以及为什么这通常不是一个好主意,请参阅this blog post

update :似乎有no way可以动态更新或更改Python3函数中的局部变量,因此calc3和类似的变体不再可能。我现在能想到的唯一兼容python3的解决方案就是使用globals

代码语言:javascript
复制
def calc4(self, x) :
        # Automatically copy every class variable in globals
        globals().update(self.__dict__)
        sqrt, exp, pi = np.sqrt, np.exp, np.pi
        return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
                * exp( -(x-x0)**2/w**2 )
                * (1+s*(x-x0)**2) + y0 )

再说一次,这是一种糟糕的做法。

票数 55
EN

Stack Overflow用户

发布于 2009-12-31 13:56:38

实际上,self不是一个关键字,它只是Python语言中实例方法的第一个参数的常规名称。第一个参数是不能跳过的,因为它是一个方法知道它被调用在你的类的哪个实例上的唯一机制。

票数 33
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1984104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档