标签归档:call

从python中运行bash脚本

问题:从python中运行bash脚本

我的以下代码有问题:

callBash.py:

import subprocess
print "start"
subprocess.call("sleep.sh")
print "end"

sleep.sh:

sleep 10

我希望10秒钟后打印“结束”。(我知道这是一个愚蠢的示例,我可以简单地在python中睡眠,但是这个简单的sleep.sh文件只是一个测试)

I have a problem with the following code:

callBash.py:

import subprocess
print "start"
subprocess.call("sleep.sh")
print "end"

sleep.sh:

sleep 10

I want the “end” to be printed after 10s. (I know that this is a dumb example, I could simply sleep within python, but this simple sleep.sh file was just as a test)


回答 0

使sleep.sh可执行并添加shell=True到参数列表中(如先前答案中所建议)可以正常工作。根据搜索路径,您可能还需要添加./或其他合适的路径。(即,更改"sleep.sh""./sleep.sh"。)

shell=True不需要的参数,如果bash脚本的第一行是一个外壳的路径(一个Posix的系统如Linux下); 例如,#!/bin/bash

Making sleep.sh executable and adding shell=True to the parameter list (as suggested in previous answers) works ok. Depending on the search path, you may also need to add ./ or some other appropriate path. (Ie, change "sleep.sh" to "./sleep.sh".)

The shell=True parameter is not needed (under a Posix system like Linux) if the first line of the bash script is a path to a shell; for example, #!/bin/bash.


回答 1

如果sleep.sh具有shebang #!/bin/sh并且它具有适当的文件权限-运行chmod u+rx sleep.sh以确保它已经在其中,$PATH则您的代码应按原样工作:

import subprocess

rc = subprocess.call("sleep.sh")

如果脚本不在PATH中,则指定它的完整路径,例如,如果它在当前工作目录中:

from subprocess import call

rc = call("./sleep.sh")

如果脚本没有shebang,则需要指定shell=True

rc = call("./sleep.sh", shell=True)

如果脚本没有可执行权限,并且您无法更改它(例如,通过运行),os.chmod('sleep.sh', 0o755)则可以将脚本作为文本文件读取,然后将字符串传递给subprocess模块:

with open('sleep.sh', 'rb') as file:
    script = file.read()
rc = call(script, shell=True)

If sleep.sh has the shebang #!/bin/sh and it has appropriate file permissions — run chmod u+rx sleep.sh to make sure and it is in $PATH then your code should work as is:

import subprocess

rc = subprocess.call("sleep.sh")

If the script is not in the PATH then specify the full path to it e.g., if it is in the current working directory:

from subprocess import call

rc = call("./sleep.sh")

If the script has no shebang then you need to specify shell=True:

rc = call("./sleep.sh", shell=True)

If the script has no executable permissions and you can’t change it e.g., by running os.chmod('sleep.sh', 0o755) then you could read the script as a text file and pass the string to subprocess module instead:

with open('sleep.sh', 'rb') as file:
    script = file.read()
rc = call(script, shell=True)

回答 2

实际上,您只需要添加shell=True参数即可:

subprocess.call("sleep.sh", shell=True)

但要注意-

警告如果与不受信任的输入结合使用,使用shell = True调用系统外壳可能会带来安全隐患。有关详细信息,请参见“常用参数”下的警告。

资源

Actually, you just have to add the shell=True argument:

subprocess.call("sleep.sh", shell=True)

But beware –

Warning Invoking the system shell with shell=True can be a security hazard if combined with untrusted input. See the warning under Frequently Used Arguments for details.

source


回答 3

如果有人希望通过参数调用脚本

import subprocess

val = subprocess.check_call("./script.sh '%s'" % arg, shell=True)

请记住在传递之前使用str(arg)将args转换为字符串。

这可以用来传递任意多个参数:

subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)

If someone looking for calling a script with arguments

import subprocess

val = subprocess.check_call("./script.sh '%s'" % arg, shell=True)

Remember to convert the args to string before passing, using str(arg).

This can be used to pass as many arguments as desired:

subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)

回答 4

确保sleep.sh具有执行权限,并使用来运行它shell=True

#!/usr/bin/python

import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"

Make sure that sleep.sh has execution permissions, and run it with shell=True:

#!/usr/bin/python

import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"

回答 5

如果chmod不起作用,那么您也可以尝试

import os
os.system('sh script.sh')
#you can also use bash instead of sh

由我测试谢谢

If chmod not working then you also try

import os
os.system('sh script.sh')
#you can also use bash instead of sh

test by me thanks


回答 6

添加一个答案是因为询问了如何从python运行bash脚本后我被定向到了这里。OSError: [Errno 2] file not found如果您的脚本接受参数,则会收到错误消息。假设您的脚本输入了一个sleep time参数:subprocess.call("sleep.sh 10")将无法工作,您必须将其作为数组传递:subprocess.call(["sleep.sh", 10])

Adding an answer because I was directed here after asking how to run a bash script from python. You receive an error OSError: [Errno 2] file not found if your script takes in parameters. Lets say for instance your script took in a sleep time parameter: subprocess.call("sleep.sh 10") will not work, you must pass it as an array: subprocess.call(["sleep.sh", 10])


Python __call__特殊方法的实际示例

问题:Python __call__特殊方法的实际示例

我知道__call__调用类的实例时会触发类中的方法。但是,我不知道何时可以使用这种特殊方法,因为一个人可以简单地创建一个新方法并执行在__call__方法中完成的相同操作,而无需调用实例,而可以调用该方法。

如果有人给我这种特殊方法的实际用法,我将不胜感激。

I know that __call__ method in a class is triggered when the instance of a class is called. However, I have no idea when I can use this special method, because one can simply create a new method and perform the same operation done in __call__ method and instead of calling the instance, you can call the method.

I would really appreciate it if someone gives me a practical usage of this special method.


回答 0

Django表单模块__call__很好地使用了方法来实现用于表单验证的一致API。您可以在Django中将自己的验证器作为函数编写。

def custom_validator(value):
    #your validation logic

Django有一些默认的内置验证器,例如电子邮件验证器,URL验证器等,它们大体上属于RegEx验证器。为了清晰地实现这些,Django求助于可调用类(而不是函数)。它在RegexValidator中实现默认的Regex验证逻辑,然后扩展这些类以进行其他验证。

class RegexValidator(object):
    def __call__(self, value):
        # validation logic

class URLValidator(RegexValidator):
    def __call__(self, value):
        super(URLValidator, self).__call__(value)
        #additional logic

class EmailValidator(RegexValidator):
    # some logic

现在,可以使用相同的语法调用自定义函数和内置的EmailValidator。

for v in [custom_validator, EmailValidator()]:
    v(value) # <-----

如您所见,Django中的此实现类似于其他人在下面的答案中解释的实现。可以通过其他任何方式实现吗?您可以,但是恕我直言,对于像Django这样的大型框架,它不那么易读或易于扩展。

Django forms module uses __call__ method nicely to implement a consistent API for form validation. You can write your own validator for a form in Django as a function.

def custom_validator(value):
    #your validation logic

Django has some default built-in validators such as email validators, url validators etc., which broadly fall under the umbrella of RegEx validators. To implement these cleanly, Django resorts to callable classes (instead of functions). It implements default Regex Validation logic in a RegexValidator and then extends these classes for other validations.

class RegexValidator(object):
    def __call__(self, value):
        # validation logic

class URLValidator(RegexValidator):
    def __call__(self, value):
        super(URLValidator, self).__call__(value)
        #additional logic

class EmailValidator(RegexValidator):
    # some logic

Now both your custom function and built-in EmailValidator can be called with the same syntax.

for v in [custom_validator, EmailValidator()]:
    v(value) # <-----

As you can see, this implementation in Django is similar to what others have explained in their answers below. Can this be implemented in any other way? You could, but IMHO it will not be as readable or as easily extensible for a big framework like Django.


回答 1

本示例使用备忘录,基本上将值存储在表(在这种情况下为字典)中,因此您以后可以查找它们,而无需重新计算它们。

在这里,我们使用带有__call__方法的简单类(通过可调用对象)来计算阶乘,而不是包含静态变量的阶乘函数(这在Python中是不可能的)。

class Factorial:
    def __init__(self):
        self.cache = {}
    def __call__(self, n):
        if n not in self.cache:
            if n == 0:
                self.cache[n] = 1
            else:
                self.cache[n] = n * self.__call__(n-1)
        return self.cache[n]

fact = Factorial()

现在,您拥有一个fact可以调用的对象,就像其他所有函数一样。例如

for i in xrange(10):                                                             
    print("{}! = {}".format(i, fact(i)))

# output
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880

而且它也是有状态的。

This example uses memoization, basically storing values in a table (dictionary in this case) so you can look them up later instead of recalculating them.

Here we use a simple class with a __call__ method to calculate factorials (through a callable object) instead of a factorial function that contains a static variable (as that’s not possible in Python).

class Factorial:
    def __init__(self):
        self.cache = {}
    def __call__(self, n):
        if n not in self.cache:
            if n == 0:
                self.cache[n] = 1
            else:
                self.cache[n] = n * self.__call__(n-1)
        return self.cache[n]

fact = Factorial()

Now you have a fact object which is callable, just like every other function. For example

for i in xrange(10):                                                             
    print("{}! = {}".format(i, fact(i)))

# output
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880

And it is also stateful.


回答 2

我发现它很有用,因为它允许我创建易于使用的API(您有一些需要一些特定参数的可调用对象),并且易于实现,因为您可以使用面向对象的实践。

以下是我昨天编写的代码,该代码使hashlib.foo散列整个文件而不是字符串的方法的版本变了:

# filehash.py
import hashlib


class Hasher(object):
    """
    A wrapper around the hashlib hash algorithms that allows an entire file to
    be hashed in a chunked manner.
    """
    def __init__(self, algorithm):
        self.algorithm = algorithm

    def __call__(self, file):
        hash = self.algorithm()
        with open(file, 'rb') as f:
            for chunk in iter(lambda: f.read(4096), ''):
                hash.update(chunk)
        return hash.hexdigest()


md5    = Hasher(hashlib.md5)
sha1   = Hasher(hashlib.sha1)
sha224 = Hasher(hashlib.sha224)
sha256 = Hasher(hashlib.sha256)
sha384 = Hasher(hashlib.sha384)
sha512 = Hasher(hashlib.sha512)

此实现使我能够以类似于功能的方式使用hashlib.foo功能:

from filehash import sha1
print sha1('somefile.txt')

当然,我可以用其他方式实现它,但是在这种情况下,这似乎是一种简单的方法。

I find it useful because it allows me to create APIs that are easy to use (you have some callable object that requires some specific arguments), and are easy to implement because you can use Object Oriented practices.

The following is code I wrote yesterday that makes a version of the hashlib.foo methods that hash entire files rather than strings:

# filehash.py
import hashlib


class Hasher(object):
    """
    A wrapper around the hashlib hash algorithms that allows an entire file to
    be hashed in a chunked manner.
    """
    def __init__(self, algorithm):
        self.algorithm = algorithm

    def __call__(self, file):
        hash = self.algorithm()
        with open(file, 'rb') as f:
            for chunk in iter(lambda: f.read(4096), ''):
                hash.update(chunk)
        return hash.hexdigest()


md5    = Hasher(hashlib.md5)
sha1   = Hasher(hashlib.sha1)
sha224 = Hasher(hashlib.sha224)
sha256 = Hasher(hashlib.sha256)
sha384 = Hasher(hashlib.sha384)
sha512 = Hasher(hashlib.sha512)

This implementation allows me to use the functions in a similar fashion to the hashlib.foo functions:

from filehash import sha1
print sha1('somefile.txt')

Of course I could have implemented it a different way, but in this case it seemed like a simple approach.


回答 3

__call__还用于在python中实现装饰器类。在这种情况下,当调用带有装饰器的方法时,将调用类的实例。

class EnterExitParam(object):

    def __init__(self, p1):
        self.p1 = p1

    def __call__(self, f):
        def new_f():
            print("Entering", f.__name__)
            print("p1=", self.p1)
            f()
            print("Leaving", f.__name__)
        return new_f


@EnterExitParam("foo bar")
def hello():
    print("Hello")


if __name__ == "__main__":
    hello()

__call__ is also used to implement decorator classes in python. In this case the instance of the class is called when the method with the decorator is called.

class EnterExitParam(object):

    def __init__(self, p1):
        self.p1 = p1

    def __call__(self, f):
        def new_f():
            print("Entering", f.__name__)
            print("p1=", self.p1)
            f()
            print("Leaving", f.__name__)
        return new_f


@EnterExitParam("foo bar")
def hello():
    print("Hello")


if __name__ == "__main__":
    hello()

回答 4

是的,当您知道要处理对象时,完全有可能(在很多情况下建议使用)显式方法调用。但是,有时您要处理期望可调用对象的代码-通常是函数,但是由于__call__您可以构建更复杂的对象,实例数据和更多方法来委派仍可调用的重复性任务等。

另外,有时您同时将对象用于复杂的任务(编写专用类是有意义的)和对象将用于简单任务(已存在于函数中,或者更容易编写为函数)使用。要拥有一个通用的接口,您要么必须编写用期望的接口包装这些函数的微型类,要么保留这些函数并使更复杂的对象可调用。让我们以线程为例。Thread来自标准库模块threading对象需要一个可调用的target参数(即在新线程中执行的操作)。对于可调用对象,您不仅可以使用函数,还可以传递其他对象,例如相对复杂的工作程序,该工作程序从其他线程获取要执行的任务并依次执行:

class Worker(object):
    def __init__(self, *args, **kwargs):
        self.queue = queue.Queue()
        self.args = args
        self.kwargs = kwargs

    def add_task(self, task):
        self.queue.put(task)

    def __call__(self):
        while True:
            next_action = self.queue.get()
            success = next_action(*self.args, **self.kwargs)
            if not success:
               self.add_task(next_action)

这只是我脑中浮现的一个例子,但我认为它已经足够复杂,足以保证上课。仅使用函数很难做到这一点,至少它需要返回两个函数,并且这种情况正在逐渐变得复杂。一个可以重命名__call__到别的东西,并通过绑定方法,但是这使得代码稍微不太明显的创建线程,并且不会增加任何价值。

Yes, when you know you’re dealing with objects, it’s perfectly possible (and in many cases advisable) to use an explicit method call. However, sometimes you deal with code that expects callable objects – typically functions, but thanks to __call__ you can build more complex objects, with instance data and more methods to delegate repetitive tasks, etc. that are still callable.

Also, sometimes you’re using both objects for complex tasks (where it makes sense to write a dedicated class) and objects for simple tasks (that already exist in functions, or are more easily written as functions). To have a common interface, you either have to write tiny classes wrapping those functions with the expected interface, or you keep the functions functions and make the more complex objects callable. Let’s take threads as example. The Thread objects from the standard libary module threading want a callable as target argument (i.e. as action to be done in the new thread). With a callable object, you are not restricted to functions, you can pass other objects as well, such as a relatively complex worker that gets tasks to do from other threads and executes them sequentially:

class Worker(object):
    def __init__(self, *args, **kwargs):
        self.queue = queue.Queue()
        self.args = args
        self.kwargs = kwargs

    def add_task(self, task):
        self.queue.put(task)

    def __call__(self):
        while True:
            next_action = self.queue.get()
            success = next_action(*self.args, **self.kwargs)
            if not success:
               self.add_task(next_action)

This is just an example off the top of my head, but I think it is already complex enough to warrant the class. Doing this only with functions is hard, at least it requires returning two functions and that’s slowly getting complex. One could rename __call__ to something else and pass a bound method, but that makes the code creating the thread slightly less obvious, and doesn’t add any value.


回答 5

基于类的装饰器__call__用来引用包装的函数。例如:

class Deco(object):
    def __init__(self,f):
        self.f = f
    def __call__(self, *args, **kwargs):
        print args
        print kwargs
        self.f(*args, **kwargs)

Artima.com上的各种选项都有很好的描述

Class-based decorators use __call__ to reference the wrapped function. E.g.:

class Deco(object):
    def __init__(self,f):
        self.f = f
    def __call__(self, *args, **kwargs):
        print args
        print kwargs
        self.f(*args, **kwargs)

There is a good description of the various options here at Artima.com


回答 6

IMHO __call__方法和闭包为我们提供了一种在Python中创建STRATEGY设计模式的自然方法。我们定义了一系列算法,将每个算法封装在一起,使其可互换,最后我们可以执行一组通用步骤,例如,计算文件的哈希值。

IMHO __call__ method and closures give us a natural way to create STRATEGY design pattern in Python. We define a family of algorithms, encapsulate each one, make them interchangeable and in the end we can execute a common set of steps and, for example, calculate a hash for a file.


回答 7

我只是偶然发现了一种我认为很美的__call__()音乐会__getattr__()。它允许您在对象内部隐藏JSON / HTTP /(however_serialized)API的多个级别。

__getattr__()部分负责迭代地返回相同类的修改后的实例,并一次填充一个以上的属性。然后,在用尽所有信息之后,__call__()接管您传入的所有参数。

例如,使用该模型,您可以进行调用,例如api.v2.volumes.ssd.update(size=20),最终导致对的PUT请求https://some.tld/api/v2/volumes/ssd/update

特定的代码是OpenStack中特定卷后端的块存储驱动程序,您可以在此处查看:https : //github.com/openstack/cinder/blob/master/cinder/volume/drivers/nexenta/jsonrpc.py

编辑:更新了链接以指向主修订。

I just stumbled upon a usage of __call__() in concert with __getattr__() which I think is beautiful. It allows you to hide multiple levels of a JSON/HTTP/(however_serialized) API inside an object.

The __getattr__() part takes care of iteratively returning a modified instance of the same class, filling in one more attribute at a time. Then, after all information has been exhausted, __call__() takes over with whatever arguments you passed in.

Using this model, you can for example make a call like api.v2.volumes.ssd.update(size=20), which ends up in a PUT request to https://some.tld/api/v2/volumes/ssd/update.

The particular code is a block storage driver for a certain volume backend in OpenStack, you can check it out here: https://github.com/openstack/cinder/blob/master/cinder/volume/drivers/nexenta/jsonrpc.py

EDIT: Updated the link to point to master revision.


回答 8

指定一个__metaclass__并覆盖该__call__方法,并让指定的元类的__new__方法返回该类的实例,中提琴表示您具有带有方法的“函数”。

Specify a __metaclass__ and override the __call__ method, and have the specified meta classes’ __new__ method return an instance of the class, viola you have a “function” with methods.


回答 9

我们可以使用__call__method来将其他类方法用作静态方法。

    class _Callable:
        def __init__(self, anycallable):
            self.__call__ = anycallable

    class Model:

        def get_instance(conn, table_name):

            """ do something"""

        get_instance = _Callable(get_instance)

    provs_fac = Model.get_instance(connection, "users")             

We can use __call__ method to use other class methods as static methods.

    class _Callable:
        def __init__(self, anycallable):
            self.__call__ = anycallable

    class Model:

        def get_instance(conn, table_name):

            """ do something"""

        get_instance = _Callable(get_instance)

    provs_fac = Model.get_instance(connection, "users")             

回答 10

一个常见的示例是__call__in functools.partial,这是一个简化的版本(Python> = 3.5):

class partial:
    """New function with partial application of the given arguments and keywords."""

    def __new__(cls, func, *args, **kwargs):
        if not callable(func):
            raise TypeError("the first argument must be callable")
        self = super().__new__(cls)

        self.func = func
        self.args = args
        self.kwargs = kwargs
        return self

    def __call__(self, *args, **kwargs):
        return self.func(*self.args, *args, **self.kwargs, **kwargs)

用法:

def add(x, y):
    return x + y

inc = partial(add, y=1)
print(inc(41))  # 42

One common example is the __call__ in functools.partial, here is a simplified version (with Python >= 3.5):

class partial:
    """New function with partial application of the given arguments and keywords."""

    def __new__(cls, func, *args, **kwargs):
        if not callable(func):
            raise TypeError("the first argument must be callable")
        self = super().__new__(cls)

        self.func = func
        self.args = args
        self.kwargs = kwargs
        return self

    def __call__(self, *args, **kwargs):
        return self.func(*self.args, *args, **self.kwargs, **kwargs)

Usage:

def add(x, y):
    return x + y

inc = partial(add, y=1)
print(inc(41))  # 42

回答 11

函数调用运算符。

class Foo:
    def __call__(self, a, b, c):
        # do something

x = Foo()
x(1, 2, 3)

__call__方法可用于重新定义的/重新初始化相同的对象。通过将参数传递给对象,还有助于将类的实例/对象用作函数。

The function call operator.

class Foo:
    def __call__(self, a, b, c):
        # do something

x = Foo()
x(1, 2, 3)

The __call__ method can be used to redefined/re-initialize the same object. It also facilitates the use of instances/objects of a class as functions by passing arguments to the objects.


回答 12

我发现使用可调用对象的好地方,那些定义__call__(),是使用Python中的函数式编程功能时,比如map()filter()reduce()

在普通函数或lambda函数上使用可调用对象的最佳时间是逻辑复杂且需要保留某些状态或使用其他未传递给__call__()函数的信息时。

以下是一些代码,它们使用可调用对象和,根据文件名的扩展名过滤文件名filter()

可调用:

import os

class FileAcceptor(object):
    def __init__(self, accepted_extensions):
        self.accepted_extensions = accepted_extensions

    def __call__(self, filename):
        base, ext = os.path.splitext(filename)
        return ext in self.accepted_extensions

class ImageFileAcceptor(FileAcceptor):
    def __init__(self):
        image_extensions = ('.jpg', '.jpeg', '.gif', '.bmp')
        super(ImageFileAcceptor, self).__init__(image_extensions)

用法:

filenames = [
    'me.jpg',
    'me.txt',
    'friend1.jpg',
    'friend2.bmp',
    'you.jpeg',
    'you.xml']

acceptor = ImageFileAcceptor()
image_filenames = filter(acceptor, filenames)
print image_filenames

输出:

['me.jpg', 'friend1.jpg', 'friend2.bmp', 'you.jpeg']

I find a good place to use callable objects, those that define __call__(), is when using the functional programming capabilities in Python, such as map(), filter(), reduce().

The best time to use a callable object over a plain function or a lambda function is when the logic is complex and needs to retain some state or uses other info that in not passed to the __call__() function.

Here’s some code that filters file names based upon their filename extension using a callable object and filter().

Callable:

import os

class FileAcceptor(object):
    def __init__(self, accepted_extensions):
        self.accepted_extensions = accepted_extensions

    def __call__(self, filename):
        base, ext = os.path.splitext(filename)
        return ext in self.accepted_extensions

class ImageFileAcceptor(FileAcceptor):
    def __init__(self):
        image_extensions = ('.jpg', '.jpeg', '.gif', '.bmp')
        super(ImageFileAcceptor, self).__init__(image_extensions)

Usage:

filenames = [
    'me.jpg',
    'me.txt',
    'friend1.jpg',
    'friend2.bmp',
    'you.jpeg',
    'you.xml']

acceptor = ImageFileAcceptor()
image_filenames = filter(acceptor, filenames)
print image_filenames

Output:

['me.jpg', 'friend1.jpg', 'friend2.bmp', 'you.jpeg']

回答 13

现在为时已晚,但我举一个例子。假设您有一Vector堂课和一Point堂课。两者都x, y作为位置参数。假设您要创建一个函数来移动要放在矢量上的点。

4个解决方案

  • put_point_on_vec(point, vec)

  • 使其成为vector类的方法。例如 my_vec.put_point(point)

  • 使它成为Point该类的一个方法。my_point.put_on_vec(vec)
  • Vector工具__call__,因此您可以像my_vec_instance(point)

这实际上是我正在研究的一些示例的一部分,该指南针对用数学解释的Dunder方法指南(我迟早要发布)。

我离开了移动点本身的逻辑,因为这不是这个问题的目的

This is too late but I’m giving an example. Imagine you have a Vector class and a Point class. Both take x, y as positional args. Let’s imagine you want to create a function that moves the point to be put on the vector.

4 Solutions

  • put_point_on_vec(point, vec)

  • Make it a method on the vector class. e.g my_vec.put_point(point)

  • Make it a method on the Point class. my_point.put_on_vec(vec)
  • Vector implements __call__, So you can use it like my_vec_instance(point)

This is actually part of some examples I’m working on for a guide for dunder methods explained with Maths that I’m gonna release sooner or later.

I left the logic of moving the point itself because this is not what this question is about


类中的Python调用函数

问题:类中的Python调用函数

我有这段代码可以计算两个坐标之间的距离。这两个函数都在同一类中。

但是,如何在函数distToPoint中调用该函数isNear

class Coordinates:
    def distToPoint(self, p):
        """
        Use pythagoras to find distance
        (a^2 = b^2 + c^2)
        """
        ...

    def isNear(self, p):
        distToPoint(self, p)
        ...

I have this code which calculates the distance between two coordinates. The two functions are both within the same class.

However how do I call the function distToPoint in the function isNear?

class Coordinates:
    def distToPoint(self, p):
        """
        Use pythagoras to find distance
        (a^2 = b^2 + c^2)
        """
        ...

    def isNear(self, p):
        distToPoint(self, p)
        ...

回答 0

由于这些是成员函数,因此在实例上将其称为成员函数self

def isNear(self, p):
    self.distToPoint(p)
    ...

Since these are member functions, call it as a member function on the instance, self.

def isNear(self, p):
    self.distToPoint(p)
    ...

回答 1

那是行不通的,因为distToPoint它在您的类内部,因此如果要引用它,则需要在类名前面加上前缀,例如:classname.distToPoint(self, p)。但是,您不应该那样做。更好的方法是直接通过类实例(这是类方法的第一个参数)引用该方法,如下所示:self.distToPoint(p)

That doesn’t work because distToPoint is inside your class, so you need to prefix it with the classname if you want to refer to it, like this: classname.distToPoint(self, p). You shouldn’t do it like that, though. A better way to do it is to refer to the method directly through the class instance (which is the first argument of a class method), like so: self.distToPoint(p).