- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用类重写一些代码。在某些时候,我想要的是使用对象的每个实例的参数值为成员函数分配一个特定的定义。
来自其他语言(JavaScript、C++、Haskell、Fortran 等),我正在努力理解一些关于 Python 的东西。一件事是类方法中 self 的以下区别。
例如,下面的代码显然是行不通的:
class fdf:
def f(x):
return 666
class gdg(fdf):
def sq():
return 7*7
hg = gdg()
hf = fdf()
print(hf.f(),hg.f(),hg.sq())
给出错误“sq() 采用 0 个位置参数,但给出了 1 个”。
据我所知,原因是在执行时函数被传递给调用对象(调用 sq 的实例)的引用作为第一个参数,然后我们可能会传递任何其他参数/参数已经定义/调用了 sq 。所以解决办法很简单:把sq的代码改成def sq(self):
。事实上,Python tutorial 1 似乎 建议对象方法应始终以 self
作为第一个参数来定义。这样做我们得到预期的 666 666 49
。到目前为止一切顺利。
但是,当我尝试像这样实现我的类时:
class Activation:
def nonLinearBipolarStep(self,x,string=None):
if not string: return (-1 if x<0 else 1 )
else: return ('-' if x<0 else '1')
default='bipolar'
activationFunctions = {
'bipolar': nonLinearBipolarStep ,
}
def _getActivation(self,func=default):
return self.activationFunctions.get(func,self.activationFunctions.get(self.default))
def __init__(self,func=None):
if func == None: func=self.default
self.run = self._getActivation(func)
ag = Activation()
print(ag.run(4))
我得到了错误
nonLinearBipolarStep() missing 1 required positional argument: 'x'
但是,解决方法(解决方案??)是将不带参数 self
(!) 的 step 函数定义为
def nonLinearBipolarStep(x,string=None):
然后我得到了 1
的预期行为(至少对于这个简单的测试)。所以,这里不仅不需要 self
,而且在这里使用它甚至是不正确的!
但是根据上面提到的教程,或者像this 这样的线程中的答案。 2或 this 3 ,在我看来这段代码不应该工作......或者应该在某些时候产生一些意想不到的后果(?)。确实,如果我在定义中删除对 self
的所有引用_getActivation
我收到错误消息 _getActivation() takes from 0 to 1 positional arguments but 2 were given
根据该规则我可以理解。
线程"Why is self not used in this method" 4没有给我提供明确的答案:上面代码的哪些语法细节告诉我不需要 self
?例如,该代码与本教程示例有何不同
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
?实例化此类按预期工作,但如果没有定义,它会提示缺少参数(我知道它可以是任何标签)。
这让我怀疑我的代码是否没有以某种方式隐藏定时炸弹:self
是否作为 x
的值传递?它按预期工作,所以我会说不,但后来我面临着这个难题。
我想我遗漏了该语言的一些关键思想。我承认我也在为引用 OP 的问题而苦苦挣扎 3在问^。
[^]:在 JS 中,只需在函数体中使用 this
,并且函数本身被定义为对象原型(prototype)的成员或实例成员,然后被正确分配使用。 ..这个
。
编辑:线很长。对于那些浏览寻求帮助的人,如果您是 Python 的新手,那么您可能需要检查所选的解决方案及其注释。但是,如果您已经了解 Python 中的绑定(bind)/未绑定(bind)方法,您只想直接检查描述符的使用,如 Blckknght 的回答中所述。我最终在要运行的作业中使用 __get__
在我的代码中选择了这种方式。
最佳答案
self
?在 Python 中,每个普通 方法都被迫接受一个通常名为 self
的参数。 .这是类的一个实例——一个对象。这就是 Python 方法与类的状态交互的方式。
您可以随意重命名此参数。但它将始终具有相同的值:
>>> class Class:
def method(foo): #
print(foo)
>>> cls = Class()
>>> cls.method()
<__main__.F object at 0x03E41D90>
>>>
但是,您可能对这段代码的工作方式有何不同感到困惑:
>>> class Class:
def method(foo):
print(foo)
methods = {'method': method}
def __init__(self):
self.run = self.methods['method']
>>> cls = Class()
>>> cls.run(3)
3
>>>
这是因为 Python 中绑定(bind)和未绑定(bind)方法之间的区别。
当我们在 __init__()
中执行此操作时:
self.run = self.methods['method']
我们指的是unbound 方法method
.这意味着我们对 method
的引用未绑定(bind)到 Class
的任何特定实例,因此,Python 不会强制 method
接受一个对象实例。因为它没有人可以给。
上面的代码和这样做是一样的:
>>> class Class:
def method(foo):
print(foo)
>>> Class.method(3)
3
>>>
在这两个示例中,我们都调用了方法 method
类对象 Class
,并且不是 Class
的实例对象。
我们可以通过检查 repr
来进一步了解这种区别对于绑定(bind)和未绑定(bind)方法:
>>> class Class:
def method(foo):
print(foo)
>>> Class.method
<function Class.method at 0x03E43D68>
>>> cls = Class()
>>> cls.method
<bound method Class.method of <__main__.Class object at 0x03BD2FB0>>
>>>
如您所见,在第一个示例中我们执行 Class.method
, Python 显示: <function Class.method at 0x03E43D68>
.我对你撒了一点谎。当我们有一个类的未绑定(bind)方法时,Python 将它们视为普通函数。所以method
只是一个未绑定(bind)到“类”的任何实例的函数。
但是在第二个例子中,当我们创建一个 Class
的实例时, 然后访问 method
它的对象,我们看到打印:<bound method Class.method of <__main__.Class object at 0x03BD2FB0>>
.
要注意的关键部分是bound method Class.method
.这意味着 method
**绑定(bind)**到cls
- Class
的一个特定实例.
正如@jonshapre 所提到的,像您的示例中那样编写代码会导致混淆(正如这个问题所证明的那样)和错误。如果您简单地定义 nonLinearBipolarStep()
会更好在Activation
之外 ,并从 Activation.activation_functions
的内部引用它:
def nonLinearBipolarStep(self,x,string=None):
if not string: return (-1 if x<0 else 1 )
else: return ('-' if x<0 else '1')
class Activation:
activation_functions = {
'bipolar': nonLinearBipolarStep,
}
...
I guess a more specific question would be: what should I pay attention to on that code in order to become evident that
ag.run(x)
would be a call to an unbound function?
如果你还想让nonLinearBipolarStep
不受约束,那么我建议只是小心。如果您认为您的方法会产生最干净的代码,那就去做吧,但请确保您知道自己在做什么以及您的代码将具有的行为。
如果您仍想向您类(class)的用户表明 ag.run()
将是静态的,您可以在某个地方的文档字符串中记录它,但这是用户根本不应该关心的事情。
关于Python 类方法 : when is self not needed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44741054/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!