标签归档:function

Python函数属性-使用和滥用

问题:Python函数属性-使用和滥用

没有多少人知道此功能,但是Python的函数(和方法)可以具有attribute。看哪:

>>> def foo(x):
...     pass
...     
>>> foo.score = 10
>>> dir(foo)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name', 'score']
>>> foo.score
10
>>> foo.score += 1
>>> foo.score
11

Python中此功能的可能用法和滥用是什么?我知道的一个很好的用法是PLY使用docstring将语法规则与方法相关联。但是自定义属性呢?是否有充分的理由使用它们?

Not many are aware of this feature, but Python’s functions (and methods) can have attributes. Behold:

>>> def foo(x):
...     pass
...     
>>> foo.score = 10
>>> dir(foo)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name', 'score']
>>> foo.score
10
>>> foo.score += 1
>>> foo.score
11

What are the possible uses and abuses of this feature in Python ? One good use I’m aware of is PLY‘s usage of the docstring to associate a syntax rule with a method. But what about custom attributes ? Are there good reasons to use them ?


回答 0

我通常使用函数属性作为注释的存储。假设我想以C#的方式编写(表示某种方法应该成为Web服务接口的一部分)

class Foo(WebService):
    @webmethod
    def bar(self, arg1, arg2):
         ...

然后我可以定义

def webmethod(func):
    func.is_webmethod = True
    return func

然后,当Web服务调用到达时,我查找该方法,检查基础函数是否具有is_webmethod属性(实际值无关紧要),如果该方法不存在或不打算通过Web调用,则拒绝该服务。

I typically use function attributes as storage for annotations. Suppose I want to write, in the style of C# (indicating that a certain method should be part of the web service interface)

class Foo(WebService):
    @webmethod
    def bar(self, arg1, arg2):
         ...

then I can define

def webmethod(func):
    func.is_webmethod = True
    return func

Then, when a webservice call arrives, I look up the method, check whether the underlying function has the is_webmethod attribute (the actual value is irrelevant), and refuse the service if the method is absent or not meant to be called over the web.


回答 1

我已经将它们用作函数的静态变量。例如,给出以下C代码:

int fn(int i)
{
    static f = 1;
    f += i;
    return f;
}

我可以在Python中类似地实现该功能:

def fn(i):
    fn.f += i
    return fn.f
fn.f = 1

这肯定属于频谱的“滥用”端。

I’ve used them as static variables for a function. For example, given the following C code:

int fn(int i)
{
    static f = 1;
    f += i;
    return f;
}

I can implement the function similarly in Python:

def fn(i):
    fn.f += i
    return fn.f
fn.f = 1

This would definitely fall into the “abuses” end of the spectrum.


回答 2

您可以用JavaScript的方式来做对象…虽然没有任何意义,但是它是可行的;)

>>> def FakeObject():
...   def test():
...     print "foo"
...   FakeObject.test = test
...   return FakeObject
>>> x = FakeObject()
>>> x.test()
foo

You can do objects the JavaScript way… It makes no sense but it works ;)

>>> def FakeObject():
...   def test():
...     print "foo"
...   FakeObject.test = test
...   return FakeObject
>>> x = FakeObject()
>>> x.test()
foo

回答 3

我很少使用它们,但是它们可以很方便:

def log(msg):
   log.logfile.write(msg)

现在,我可以log在整个模块中使用,只需设置即可重定向输出log.logfile。有很多其他方法可以实现这一点,但是这种方法轻巧而简单。虽然我第一次这样做时闻起来很可笑,但我开始相信它闻起来比具有全局logfile变量更好。

I use them sparingly, but they can be pretty convenient:

def log(msg):
   log.logfile.write(msg)

Now I can use log throughout my module, and redirect output simply by setting log.logfile. There are lots and lots of other ways to accomplish that, but this one’s lightweight and dirt simple. And while it smelled funny the first time I did it, I’ve come to believe that it smells better than having a global logfile variable.


回答 4

函数属性可用于编写将代码和关联数据包装在一起的轻量级闭包:

#!/usr/bin/env python

SW_DELTA = 0
SW_MARK  = 1
SW_BASE  = 2

def stopwatch():
   import time

   def _sw( action = SW_DELTA ):

      if action == SW_DELTA:
         return time.time() - _sw._time

      elif action == SW_MARK:
         _sw._time = time.time()
         return _sw._time

      elif action == SW_BASE:
         return _sw._time

      else:
         raise NotImplementedError

   _sw._time = time.time() # time of creation

   return _sw

# test code
sw=stopwatch()
sw2=stopwatch()
import os
os.system("sleep 1")
print sw() # defaults to "SW_DELTA"
sw( SW_MARK )
os.system("sleep 2")
print sw()
print sw2()

1.00934004784

2.00644397736

3.01593494415

Function attributes can be used to write light-weight closures that wrap code and associated data together:

#!/usr/bin/env python

SW_DELTA = 0
SW_MARK  = 1
SW_BASE  = 2

def stopwatch():
   import time

   def _sw( action = SW_DELTA ):

      if action == SW_DELTA:
         return time.time() - _sw._time

      elif action == SW_MARK:
         _sw._time = time.time()
         return _sw._time

      elif action == SW_BASE:
         return _sw._time

      else:
         raise NotImplementedError

   _sw._time = time.time() # time of creation

   return _sw

# test code
sw=stopwatch()
sw2=stopwatch()
import os
os.system("sleep 1")
print sw() # defaults to "SW_DELTA"
sw( SW_MARK )
os.system("sleep 2")
print sw()
print sw2()

1.00934004784

2.00644397736

3.01593494415


回答 5

我创建了这个辅助装饰器来轻松设置函数属性:

def with_attrs(**func_attrs):
    """Set attributes in the decorated function, at definition time.
    Only accepts keyword arguments.
    E.g.:
        @with_attrs(counter=0, something='boing')
        def count_it():
            count_it.counter += 1
        print count_it.counter
        print count_it.something
        # Out:
        # >>> 0
        # >>> 'boing'
    """
    def attr_decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            return fn(*args, **kwargs)

        for attr, value in func_attrs.iteritems():
            setattr(wrapper, attr, value)

        return wrapper

    return attr_decorator

用例是创建工厂的集合,并查询它们可以在功能元级别创建的数据类型。
例如(非常愚蠢):

@with_attrs(datatype=list)
def factory1():
    return [1, 2, 3]

@with_attrs(datatype=SomeClass)
def factory2():
    return SomeClass()

factories = [factory1, factory2]

def create(datatype):
    for f in factories:
        if f.datatype == datatype:
            return f()
    return None

I’ve created this helper decorator to easily set function attributes:

def with_attrs(**func_attrs):
    """Set attributes in the decorated function, at definition time.
    Only accepts keyword arguments.
    E.g.:
        @with_attrs(counter=0, something='boing')
        def count_it():
            count_it.counter += 1
        print count_it.counter
        print count_it.something
        # Out:
        # >>> 0
        # >>> 'boing'
    """
    def attr_decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            return fn(*args, **kwargs)

        for attr, value in func_attrs.iteritems():
            setattr(wrapper, attr, value)

        return wrapper

    return attr_decorator

A use case is to create a collection of factories and query the data type they can create at a function meta level.
For example (very dumb one):

@with_attrs(datatype=list)
def factory1():
    return [1, 2, 3]

@with_attrs(datatype=SomeClass)
def factory2():
    return SomeClass()

factories = [factory1, factory2]

def create(datatype):
    for f in factories:
        if f.datatype == datatype:
            return f()
    return None

回答 6

有时,我使用函数的属性来缓存已计算的值。您也可以使用通用装饰器来概括此方法。注意此类功能的并发问题和副作用!

Sometimes I use an attribute of a function for caching already computed values. You can also have a generic decorator that generalizes this approach. Be aware of concurrency issues and side effects of such functions!


回答 7

我一直以为,这是唯一可能的原因,因此在逻辑上可以放置文档字符串或其他类似的东西。我知道如果我将它用于任何生产代码,都会使大多数阅读它的人感到困惑。

I was always of the assumption that the only reason this was possible was so there was a logical place to put a doc-string or other such stuff. I know if I used it for any production code it’d confuse most who read it.


如何从Python中的函数返回两个值?

问题:如何从Python中的函数返回两个值?

我想在两个单独的变量中从函数返回两个值。例如:

def select_choice():
    loop = 1
    row = 0
    while loop == 1:
        print('''Choose from the following options?:
                 1. Row 1
                 2. Row 2
                 3. Row 3''')

        row = int(input("Which row would you like to move the card from?: "))
        if row == 1:
            i = 2
            card = list_a[-1]
        elif row == 2:
            i = 1
            card = list_b[-1]
        elif row == 3:
            i = 0
            card = list_c[-1]
        return i
        return card

我希望能够分别使用这些值。当我尝试使用时return i, card,它返回a tuple,这不是我想要的。

I would like to return two values from a function in two separate variables. For example:

def select_choice():
    loop = 1
    row = 0
    while loop == 1:
        print('''Choose from the following options?:
                 1. Row 1
                 2. Row 2
                 3. Row 3''')

        row = int(input("Which row would you like to move the card from?: "))
        if row == 1:
            i = 2
            card = list_a[-1]
        elif row == 2:
            i = 1
            card = list_b[-1]
        elif row == 3:
            i = 0
            card = list_c[-1]
        return i
        return card

And I want to be able to use these values separately. When I tried to use return i, card, it returns a tuple and this is not what I want.


回答 0

您不能返回两个值,但可以返回a tuple或a list并在调用后解压缩它:

def select_choice():
    ...
    return i, card  # or [i, card]

my_i, my_card = select_choice()

在线return i, card i, card意味着创建一个元组。您也可以使用括号,例如return (i, card),但是元组是用逗号创建的,因此括号不是必需的。但是,您可以使用parens来提高代码的可读性或将元组分成多行。这同样适用于line my_i, my_card = select_choice()

如果要返回两个以上的值,请考虑使用命名的tuple。它将允许函数的调用者按名称访问返回值的字段,这样更易​​于阅读。您仍然可以按索引访问元组的项目。例如,在Schema.loadsMarshmallow框架方法中,返回的UnmarshalResult是a namedtuple。因此,您可以执行以下操作:

data, errors = MySchema.loads(request.json())
if errors:
    ...

要么

result = MySchema.loads(request.json())
if result.errors:
    ...
else:
    # use `result.data`

在其他情况下,您可以dict从函数中返回a :

def select_choice():
    ...
    return {'i': i, 'card': card, 'other_field': other_field, ...}

但是您可能要考虑返回一个实用程序类的实例,该实例包装您的数据:

class ChoiceData():
    def __init__(self, i, card, other_field, ...):
        # you can put here some validation logic
        self.i = i
        self.card = card
        self.other_field = other_field
        ...

def select_choice():
    ...
    return ChoiceData(i, card, other_field, ...)

choice_data = select_choice()
print(choice_data.i, choice_data.card)

You cannot return two values, but you can return a tuple or a list and unpack it after the call:

def select_choice():
    ...
    return i, card  # or [i, card]

my_i, my_card = select_choice()

On line return i, card i, card means creating a tuple. You can also use parenthesis like return (i, card), but tuples are created by comma, so parens are not mandatory. But you can use parens to make your code more readable or to split the tuple over multiple lines. The same applies to line my_i, my_card = select_choice().

If you want to return more than two values, consider using a named tuple. It will allow the caller of the function to access fields of the returned value by name, which is more readable. You can still access items of the tuple by index. For example in Schema.loads method Marshmallow framework returns a UnmarshalResult which is a namedtuple. So you can do:

data, errors = MySchema.loads(request.json())
if errors:
    ...

or

result = MySchema.loads(request.json())
if result.errors:
    ...
else:
    # use `result.data`

In other cases you may return a dict from your function:

def select_choice():
    ...
    return {'i': i, 'card': card, 'other_field': other_field, ...}

But you might want consider to return an instance of a utility class, which wraps your data:

class ChoiceData():
    def __init__(self, i, card, other_field, ...):
        # you can put here some validation logic
        self.i = i
        self.card = card
        self.other_field = other_field
        ...

def select_choice():
    ...
    return ChoiceData(i, card, other_field, ...)

choice_data = select_choice()
print(choice_data.i, choice_data.card)

回答 1

我想在两个单独的变量中从函数返回两个值。

您希望它在呼叫端看起来像什么?您无法编写,a = select_choice(); b = select_choice()因为那样会调用该函数两次。

值不“在变量中”返回;那不是Python的工作方式。函数返回值(对象)。变量只是给定上下文中值的名称。当您调用函数并在某处分配返回值时,您正在做的就是在调用上下文中为接收到的值命名。该函数不会为您将值“放入变量”中,赋值却会这样做(不必担心变量不是该值的“存储”,而是一个名称)。

当我尝试使用时return i, card,它返回a tuple,这不是我想要的。

实际上,这正是您想要的。您所要做的就是tuple再次分开。

而且我希望能够单独使用这些值。

因此,只需从中获取价值即可tuple

最简单的方法是打开包装:

a, b = select_choice()

I would like to return two values from a function in two separate variables.

What would you expect it to look like on the calling end? You can’t write a = select_choice(); b = select_choice() because that would call the function twice.

Values aren’t returned “in variables”; that’s not how Python works. A function returns values (objects). A variable is just a name for a value in a given context. When you call a function and assign the return value somewhere, what you’re doing is giving the received value a name in the calling context. The function doesn’t put the value “into a variable” for you, the assignment does (never mind that the variable isn’t “storage” for the value, but again, just a name).

When i tried to to use return i, card, it returns a tuple and this is not what i want.

Actually, it’s exactly what you want. All you have to do is take the tuple apart again.

And i want to be able to use these values separately.

So just grab the values out of the tuple.

The easiest way to do this is by unpacking:

a, b = select_choice()

回答 2

我认为您想要的是元组。如果使用return (i, card),则可以通过以下方式获得这两个结果:

i, card = select_choice()

I think you what you want is a tuple. If you use return (i, card), you can get these two results by:

i, card = select_choice()

回答 3

def test():
    ....
    return r1, r2, r3, ....

>> ret_val = test()
>> print ret_val
(r1, r2, r3, ....)

现在,您可以使用元组完成所有您喜欢的事情。

def test():
    ....
    return r1, r2, r3, ....

>> ret_val = test()
>> print ret_val
(r1, r2, r3, ....)

now you can do everything you like with your tuple.


回答 4

def test():
    r1 = 1
    r2 = 2
    r3 = 3
    return r1, r2, r3

x,y,z = test()
print x
print y
print z


> test.py 
1
2
3
def test():
    r1 = 1
    r2 = 2
    r3 = 3
    return r1, r2, r3

x,y,z = test()
print x
print y
print z


> test.py 
1
2
3

回答 5

这是另一种选择,如果您以列表形式返回,则很容易获得值。

def select_choice():
    ...
    return [i, card]

values = select_choice()

print values[0]
print values[1]

And this is an alternative.If you are returning as list then it is simple to get the values.

def select_choice():
    ...
    return [i, card]

values = select_choice()

print values[0]
print values[1]

回答 6

你可以试试这个

class select_choice():
    return x, y

a, b = test()

you can try this

class select_choice():
    return x, y

a, b = test()

回答 7

您还可以使用list返回多个值。检查下面的代码

def newFn():    #your function
  result = []    #defining blank list which is to be return
  r1 = 'return1'    #first value
  r2 = 'return2'    #second value
  result.append(r1)    #adding first value in list
  result.append(r2)    #adding second value in list
  return result    #returning your list

ret_val1 = newFn()[1]    #you can get any desired result from it
print ret_val1    #print/manipulate your your result

You can return more than one value using list also. Check the code below

def newFn():    #your function
  result = []    #defining blank list which is to be return
  r1 = 'return1'    #first value
  r2 = 'return2'    #second value
  result.append(r1)    #adding first value in list
  result.append(r2)    #adding second value in list
  return result    #returning your list

ret_val1 = newFn()[1]    #you can get any desired result from it
print ret_val1    #print/manipulate your your result

使用’key’和lambda表达式的python max函数

问题:使用’key’和lambda表达式的python max函数

我来自OOP背景,尝试学习python。我正在使用max使用lambda表达式返回列表中Player具有最大类型的实例的函数。totalScoreplayers

def winner():
    w = max(players, key=lambda p: p.totalScore)

该函数正确返回Player具有maximum 类型的实例totalScore。我对以下三件事感到困惑:

  1. max功能如何工作?它正在采取什么论点?我查看了文档,但听不懂。
  2. keymax函数中关键字的用途是什么?我知道它也用于sort功能上下文
  3. lambda表达式的含义?如何阅读它们?它们如何运作?

这些都是非常笨拙的概念性问题,但可以帮助我理解语言。如果您可以提供示例进行解释,将有所帮助。谢谢

I come from OOP background and trying to learn python. I am using the max function which uses a lambda expression to return the instance of type Player having maximum totalScore among the list players.

def winner():
    w = max(players, key=lambda p: p.totalScore)

The function correctly returns instance of type Player having maximum totalScore. I am confused about the following three things:

  1. How does the max function work? What are the arguments it is taking? I looked at the documentation but failed to understand.
  2. What is use of the keyword key in max function? I know it is also used in context of sort function
  3. Meaning of the lambda expression? How to read them? How do they work?

These are all very noobish conceptual questions but will help me understand the language. It would help if you could give examples to explain. Thanks


回答 0

lambda 是一个匿名函数,它等效于:

def func(p):
   return p.totalScore     

现在max变成:

max(players, key=func)

但是由于def语句是复合语句,因此不能在需要表达式的地方使用它们,这就是有时lambda使用的原因。

请注意,这lambda等效于您在的return语句中输入的内容def。因此,您不能在内使用语句lambda,仅允许使用表达式。


怎么max办?

max(a,b,c,… [,key = func])->值

使用单个可迭代参数,返回其最大的项目。具有两个或更多参数,返回最大参数。

因此,它仅返回最大的对象。


key工作如何?

在Python 2中,默认情况下会key根据对象类型(例如,字符串始终大于整数)基于一组规则比较项目。

要在比较之前修改对象,或基于特定的属性/索引进行比较,必须使用key参数。

范例1:

一个简单的示例,假设您有一个字符串形式的数字列表,但是您想按其整数值比较这些项目。

>>> lis = ['1', '100', '111', '2']

这里max使用它们的原始值比较项目(按字母顺序比较字符串,这样您就可以得到'2'输出):

>>> max(lis)
'2'

要通过整数比较项目,请使用key简单的lambda

>>> max(lis, key=lambda x:int(x))  # compare `int` version of each item
'111'

示例2:应用于max元组列表。

>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]

默认情况下,max将按第一个索引比较项目。如果第一个索引相同,则将比较第二个索引。在我的示例中,所有项目都有唯一的第一个索引,因此您将获得以下答案:

>>> max(lis)
(4, 'e')

但是,如果您想通过索引1的值比较每个项目,该怎么办?简单:使用lambda

>>> max(lis, key = lambda x: x[1])
(-1, 'z')

比较包含不同类型对象的可迭代项

混合项目清单:

lis = ['1','100','111','2', 2, 2.57]

在Python 2中,可以比较两种不同类型的项目

>>> max(lis)  # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # compare integer version of each item
'111'

但是在Python 3中,您不能再这样做了

>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
  File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    max(lis)
TypeError: unorderable types: int() > str()

但这可行,因为我们正在比较每个对象的整数版本:

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'

lambda is an anonymous function, it is equivalent to:

def func(p):
   return p.totalScore     

Now max becomes:

max(players, key=func)

But as def statements are compound statements they can’t be used where an expression is required, that’s why sometimes lambda‘s are used.

Note that lambda is equivalent to what you’d put in a return statement of a def. Thus, you can’t use statements inside a lambda, only expressions are allowed.


What does max do?

max(a, b, c, …[, key=func]) -> value

With a single iterable argument, return its largest item. With two or more arguments, return the largest argument.

So, it simply returns the object that is the largest.


How does key work?

By default in Python 2 key compares items based on a set of rules based on the type of the objects (for example a string is always greater than an integer).

To modify the object before comparison, or to compare based on a particular attribute/index, you’ve to use the key argument.

Example 1:

A simple example, suppose you have a list of numbers in string form, but you want to compare those items by their integer value.

>>> lis = ['1', '100', '111', '2']

Here max compares the items using their original values (strings are compared lexicographically so you’d get '2' as output) :

>>> max(lis)
'2'

To compare the items by their integer value use key with a simple lambda:

>>> max(lis, key=lambda x:int(x))  # compare `int` version of each item
'111'

Example 2: Applying max to a list of tuples.

>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]

By default max will compare the items by the first index. If the first index is the same then it’ll compare the second index. As in my example, all items have a unique first index, so you’d get this as the answer:

>>> max(lis)
(4, 'e')

But, what if you wanted to compare each item by the value at index 1? Simple: use lambda:

>>> max(lis, key = lambda x: x[1])
(-1, 'z')

Comparing items in an iterable that contains objects of different type:

List with mixed items:

lis = ['1','100','111','2', 2, 2.57]

In Python 2 it is possible to compare items of two different types:

>>> max(lis)  # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # compare integer version of each item
'111'

But in Python 3 you can’t do that any more:

>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
  File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    max(lis)
TypeError: unorderable types: int() > str()

But this works, as we are comparing integer version of each object:

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'

回答 1

的高度简化版本max

def max(items, key=lambda x: x):
    current = item[0]
    for item in items:
        if key(item) > key(current):
            current = item
    return current

关于lambda:

>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

Strongly simplified version of max:

def max(items, key=lambda x: x):
    current = item[0]
    for item in items:
        if key(item) > key(current):
            current = item
    return current

Regarding lambda:

>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

回答 2

max函数如何工作?

它寻找可迭代的“最大”项。我假设您可以查找内容,但如果不是,则可以循环查找,即列表或字符串。

max函数中关键字key的用途是什么?我知道它也用于排序功能的上下文中

Key是一个lambda函数,它将告诉max可迭代对象中的哪些对象大于其他对象。假设您正在排序自己创建的某个对象,而不是像整数这样的显而易见的对象。

lambda表达式的含义?如何阅读它们?它们如何运作?

这是一个更大的问题。简单来说,lambda是一个您可以传递的功能,并且其他代码也可以使用它。以这个为例:

def sum(a, b, f):
    return (f(a) + f(b))

这需要两个对象,ab和一个函数f。它调用f()每个对象,然后将它们添加在一起。所以看这个电话:

>>> sum(2, 2, lambda a:  a * 2)
8

sum()需要2,并在其上调用lambda表达式。因此f(a)变为2 * 2,变为4。然后为进行此操作b,并将两者加在一起。

用不那么简单的术语来说,lambda来自lambda演算,这是一个返回函数的函数。用于表达计算的非常酷的数学概念。你可以阅读有关在这里,然后居然明白在这里

最好多读一遍,因为lambda可能会造成混淆,而且还不清楚它们的用处。在这里检查。

How does the max function work?

It looks for the “largest” item in an iterable. I’ll assume that you can look up what that is, but if not, it’s something you can loop over, i.e. a list or string.

What is use of the keyword key in max function? I know it is also used in context of sort function

Key is a lambda function that will tell max which objects in the iterable are larger than others. Say if you were sorting some object that you created yourself, and not something obvious, like integers.

Meaning of the lambda expression? How to read them? How do they work?

That’s sort of a larger question. In simple terms, a lambda is a function you can pass around, and have other pieces of code use it. Take this for example:

def sum(a, b, f):
    return (f(a) + f(b))

This takes two objects, a and b, and a function f. It calls f() on each object, then adds them together. So look at this call:

>>> sum(2, 2, lambda a:  a * 2)
8

sum() takes 2, and calls the lambda expression on it. So f(a) becomes 2 * 2, which becomes 4. It then does this for b, and adds the two together.

In not so simple terms, lambdas come from lambda calculus, which is the idea of a function that returns a function; a very cool math concept for expressing computation. You can read about that here, and then actually understand it here.

It’s probably better to read about this a little more, as lambdas can be confusing, and it’s not immediately obvious how useful they are. Check here.


回答 3

max函数用于获取最大值iterable

迭代器可以是列表,元组,字典对象等。甚至可以像您提供的示例中那样是自定义对象。

max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.

因此,key=func基本上,我们可以将一个可选参数传递key给该函数,在该函数的基础上,对给定的迭代器/参数进行排序并返回最大值。

lambda是一个充当伪函数的python关键字。因此,当您将player对象传递给它时,它将返回player.totalScore。因此,传递给函数的iterable max将根据提供给它的对象的key totalScore进行排序,player并返回player具有maximum 的who totalScore

如果未key提供任何参数,则根据默认的Python顺序返回最大值。

例子 –

max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7

people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')

max function is used to get the maximum out of an iterable.

The iterators may be lists, tuples, dict objects, etc. Or even custom objects as in the example you provided.

max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.

So, the key=func basically allows us to pass an optional argument key to the function on whose basis is the given iterator/arguments are sorted & the maximum is returned.

lambda is a python keyword that acts as a pseudo function. So, when you pass player object to it, it will return player.totalScore. Thus, the iterable passed over to function max will sort according to the key totalScore of the player objects given to it & will return the player who has maximum totalScore.

If no key argument is provided, the maximum is returned according to default Python orderings.

Examples –

max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7

people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')

回答 4

根据文档

max(iterable [,key])
max(arg1,arg2,* args [,key])
返回可迭代的最大项目或两个或多个参数中的最大项目。

如果提供了一个位置参数,则iterable必须是非空的Iterable(例如,非空的字符串,元组或列表)。返回iterable中最大的项目。如果提供了两个或多个位置自变量,则返回最大的位置自变量。

可选的key参数指定一个单参数排序函数,例如用于list.sort()的函数。如果提供了key参数,则必须采用关键字形式(例如max(a,b,c,key = func))。

这就是说,在这种情况下,您要提供一个列表players。然后,该max函数将遍历列表中的所有项目,并将它们相互比较以获得“最大值”。

可以想象,使用复杂的对象(例如player确定其比较值)比较棘手,因此将为您提供key参数,以确定max函数如何确定每个对象的值player。在这种情况下,您使用的是lambda函数,说“对于每个pin playersget p.totalscore并将其用作比较的值”。

According to the documentation:

max(iterable[, key])
max(arg1, arg2, *args[, key])
Return the largest item in an iterable or the largest of two or more arguments.

If one positional argument is provided, iterable must be a non-empty iterable (such as a non-empty string, tuple or list). The largest item in the iterable is returned. If two or more positional arguments are provided, the largest of the positional arguments is returned.

The optional key argument specifies a one-argument ordering function like that used for list.sort(). The key argument, if supplied, must be in keyword form (for example, max(a,b,c,key=func)).

What this is saying is that in your case, you are providing a list, in this case players. Then the max function will iterate over all the items in the list and compare them to each other to get a “maximum”.

As you can imagine, with a complex object like a player determining its value for comparison is tricky, so you are given the key argument to determine how the max function will decide the value of each player. In this case, you are using a lambda function to say “for each p in players get p.totalscore and use that as his value for comparison”.


回答 5

max内置函数,该函数接受第一个参数iterable(例如列表或元组)

关键字参数key具有默认值,None但它接受要评估的函数,将其视为基于函数评估可迭代的包装器

考虑以下示例字典:

d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}

例如:

>>> max(d.keys())
'sword'

如您所见,如果只传递不带kwarg的可迭代对象(将函数传递给key),它将返回key的最大值(按字母顺序)

例如 可能不是需要按字母顺序查找键的最大值,而是可能需要根据键的长度查找最大键:

>>>max(d.keys(), key=lambda x: len(x))
'artwork'

在此示例中,lambda函数返回的键长度将被迭代,因此在评估值而不是按字母顺序考虑时,它将跟踪键的最大长度并返回具有最大长度的键

例如

>>> max(d.keys(), key=lambda x: d[x])
'friend'

在此示例中,lambda函数返回具有最大值的相应字典键的值

max is built in function which takes first argument an iterable (like list or tuple)

keyword argument key has it’s default value None but it accept function to evaluate, consider it as wrapper which evaluates iterable based on function

Consider this example dictionary:

d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}

Ex:

>>> max(d.keys())
'sword'

As you can see if you only pass the iterable without kwarg(a function to key) it is returning maximum value of key(alphabetically)

Ex. Instead of finding max value of key alphabetically you might need to find max key by length of key:

>>>max(d.keys(), key=lambda x: len(x))
'artwork'

in this example lambda function is returning length of key which will be iterated hence while evaluating values instead of considering alphabetically it will keep track of max length of key and returns key which has max length

Ex.

>>> max(d.keys(), key=lambda x: d[x])
'friend'

in this example lambda function is returning value of corresponding dictionary key which has maximum value


类中的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).


在python中定义私有模块函数

问题:在python中定义私有模块函数

根据http://www.faqs.org/docs/diveintopython/fileinfo_private.html

像大多数语言一样,Python具有私有元素的概念:

  • 私有函数,不能从其模块外部调用

但是,如果我定义两个文件:

#a.py
__num=1

和:

#b.py
import a
print a.__num

当我运行b.py它打印出1没有给出任何exceptions。diveintopython是错误的,还是我误会了某些东西?而且是有一些方法可以定义模块的功能为私有?

According to http://www.faqs.org/docs/diveintopython/fileinfo_private.html:

Like most languages, Python has the concept of private elements:

  • Private functions, which can’t be called from outside their module

However, if I define two files:

#a.py
__num=1

and:

#b.py
import a
print a.__num

when i run b.py it prints out 1 without giving any exception. Is diveintopython wrong, or did I misunderstand something? And is there some way to do define a module’s function as private?


回答 0

在Python中,“隐私”取决于“同意成年人”的协议级别-您不能强制执行它(比现实生活中的要多;-)。单个前导下划线表示您不应该 “从外部”访问它- 两个前导下划线(不带尾随下划线)可以更加有力地传达信息……但最终,它仍然取决于社交网络会议达成共识:Python的自省是有力的,以至于你无法手铐在世界上其他程序员尊重您的意愿。

((顺便说一句,尽管这是一个秘密的秘密,但对于C ++却是如此:在大多数编译器中,狡猾的编码人员只需花#define private public一行简单#include.h代码就可以对您的“隐私”进行散列…!-) )

In Python, “privacy” depends on “consenting adults'” levels of agreement – you can’t force it (any more than you can in real life;-). A single leading underscore means you’re not supposed to access it “from the outside” — two leading underscores (w/o trailing underscores) carry the message even more forcefully… but, in the end, it still depends on social convention and consensus: Python’s introspection is forceful enough that you can’t handcuff every other programmer in the world to respect your wishes.

((Btw, though it’s a closely held secret, much the same holds for C++: with most compilers, a simple #define private public line before #includeing your .h file is all it takes for wily coders to make hash of your “privacy”…!-))


回答 1

类私有模块私有之间可能会有混淆。

模块私人与启动一个下划线
这样的元件不使用时沿复制from <module_name> import *导入命令的形式; 但是,如果使用import <moudule_name>语法将其导入(请参阅Ben Wilhelm的答案),
只需从问题示例的a .__ num中删除一个下划线,并且不会在使用该from a import *语法导入a.py的模块中显示该下划线。

类私有与开始两个下划线 (又名dunder即d-ouble下分数)
这样的变量有其名“错位”,以包括类名等
它仍然可以访问的类逻辑的外面,通过重整名称。
尽管名称改编可以用作防止未经授权访问的温和预防工具,但其主要目的是防止与祖先类的类成员发生可能的名称冲突。参见亚历克斯·马特利(Alex Martelli)有趣而准确地提及成年人的同意书,因为他描述了有关这些变量的约定。

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>

There may be confusion between class privates and module privates.

A module private starts with one underscore
Such a element is not copied along when using the from <module_name> import * form of the import command; it is however imported if using the import <moudule_name> syntax (see Ben Wilhelm’s answer)
Simply remove one underscore from the a.__num of the question’s example and it won’t show in modules that import a.py using the from a import * syntax.

A class private starts with two underscores (aka dunder i.e. d-ouble under-score)
Such a variable has its name “mangled” to include the classname etc.
It can still be accessed outside of the class logic, through the mangled name.
Although the name mangling can serve as a mild prevention device against unauthorized access, its main purpose is to prevent possible name collisions with class members of the ancestor classes. See Alex Martelli’s funny but accurate reference to consenting adults as he describes the convention used in regards to these variables.

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>

回答 2

由于模块隐私不是纯粹的常规,并且由于使用import可能会或可能不会识别模块隐私,这取决于使用方式,因此未完全回答此问题。

如果您在模块中定义专用名称,则这些名称被导入到使用“ import module_name”语法的任何脚本中。因此,假设您已在示例中正确定义了a.py中的私有_num模块,如下所示。

#a.py
_num=1

..您将可以在b.py中使用模块名称符号访问它:

#b.py
import a
...
foo = a._num # 1

要仅从a.py导入非特权,必须使用from语法:

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

但是,为了清楚起见,从模块导入名称时最好是显式的,而不是用’*’导入所有名称:

#b.py
from a import name1 
from a import name2
...

This question was not fully answered, since module privacy is not purely conventional, and since using import may or may not recognize module privacy, depending on how it is used.

If you define private names in a module, those names will be imported into any script that uses the syntax, ‘import module_name’. Thus, assuming you had correctly defined in your example the module private, _num, in a.py, like so..

#a.py
_num=1

..you would be able to access it in b.py with the module name symbol:

#b.py
import a
...
foo = a._num # 1

To import only non-privates from a.py, you must use the from syntax:

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

For the sake of clarity, however, it is better to be explicit when importing names from modules, rather than importing them all with a ‘*’:

#b.py
from a import name1 
from a import name2
...

回答 3

Python允许带有双下划线前缀的私有成员。该技术在模块级别上不起作用,因此我认为这是Dive Into Python中的错误。

这是私有类函数的示例:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails

Python allows for private class members with the double underscore prefix. This technique doesn’t work at a module level so I am thinking this is a mistake in Dive Into Python.

Here is an example of private class functions:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails

回答 4

您可以添加一个内部函数:

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data

如果您确实需要该级别的隐私,则应采用类似的方法。

You can add an inner function:

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data

Something like that if you really need that level of privacy.


回答 5

这是一个古老的问题,但是标准文档现在涵盖了模块私有(一个下划线)和类私有(两个下划线)混合变量。

Python教程 » » 私有变量

This is an ancient question, but both module private (one underscore) and class-private (two underscores) mangled variables are now covered in the standard documentation:

The Python Tutorial » Classes » Private Variables


回答 6

嵌入闭包或函数是一种方法。这在JS中很常见,但非浏览器平台或浏览器工作程序则不需要。

在Python中,这似乎有些奇怪,但是如果确实需要隐藏某些东西,那可能就是这样。更重要的是,使用python API并保留需要隐藏在C(或其他语言)中的内容可能是最好的方法。如果没有,我会将代码放入函数中,调用该函数并使它返回要导出的项目。

embedded with closures or functions is one way. This is common in JS although not required for non-browser platforms or browser workers.

In Python it seems a bit strange, but if something really needs to be hidden than that might be the way. More to the point using the python API and keeping things that require to be hidden in the C (or other language) is probably the best way. Failing that I would go for putting the code inside a function, calling that and having it return the items you want to export.


回答 7

Python具有三种模式,分别是private,public和protected。在导入模块时,只能访问public模式。因此,不能从模块外部(即在导入时)调用private和protected模块。

Python has three modes via., private, public and protected .While importing a module only public mode is accessible .So private and protected modules cannot be called from outside of the module i.e., when it is imported .


忽略python多个返回值

问题:忽略python多个返回值

假设我有一个Python函数,可在一个元组中返回多个值:

def func():
    return 1, 2

有没有一种好的方法可以忽略其中一个结果,而不仅仅是分配给一个临时变量?假设我只对第一个值感兴趣,是否有比这更好的方法:

x, temp = func()

Say I have a Python function that returns multiple values in a tuple:

def func():
    return 1, 2

Is there a nice way to ignore one of the results rather than just assigning to a temporary variable? Say if I was only interested in the first value, is there a better way than this:

x, temp = func()

回答 0

一种常见的约定是对您要忽略的元组的元素使用“ _”作为变量名。例如:

def f():
    return 1, 2, 3

_, _, x = f()

One common convention is to use a “_” as a variable name for the elements of the tuple you wish to ignore. For instance:

def f():
    return 1, 2, 3

_, _, x = f()

回答 1

您可以使用x = func()[0]返回第一个值,x = func()[1]返回第二个值,依此类推。

如果您想一次获取多个值,请使用x, y = func()[2:4]

You can use x = func()[0] to return the first value, x = func()[1] to return the second, and so on.

If you want to get multiple values at a time, use something like x, y = func()[2:4].


回答 2

如果您使用的是Python 3,则可以在变量(在作业的左侧)之前使用星号,以使其成为解压缩列表。

# Example 1: a is 1 and b is [2, 3]

a, *b = [1, 2, 3]

# Example 2: a is 1, b is [2, 3], and c is 4

a, *b, c = [1, 2, 3, 4]

# Example 3: b is [1, 2] and c is 3

*b, c = [1, 2, 3]       

# Example 4: a is 1 and b is []

a, *b = [1]

If you’re using Python 3, you can you use the star before a variable (on the left side of an assignment) to have it be a list in unpacking.

# Example 1: a is 1 and b is [2, 3]

a, *b = [1, 2, 3]

# Example 2: a is 1, b is [2, 3], and c is 4

a, *b, c = [1, 2, 3, 4]

# Example 3: b is [1, 2] and c is 3

*b, c = [1, 2, 3]       

# Example 4: a is 1 and b is []

a, *b = [1]

回答 3

请记住,当您返回多个项目时,您实际上是在返回一个元组。因此,您可以执行以下操作:

def func():
    return 1, 2

print func()[0] # prints 1
print func()[1] # prints 2

Remember, when you return more than one item, you’re really returning a tuple. So you can do things like this:

def func():
    return 1, 2

print func()[0] # prints 1
print func()[1] # prints 2

回答 4

通常的做法是使用哑变量_(单个下划线),正如前面在此处指出的那样。

但是,为了避免与该变量名的其他用法冲突(请参阅响应)__,如ncoghlan所指出的那样,最好使用(双下划线)代替一次性变量。例如:

x, __ = func()

The common practice is to use the dummy variable _ (single underscore), as many have indicated here before.

However, to avoid collisions with other uses of that variable name (see this response) it might be a better practice to use __ (double underscore) instead as a throwaway variable, as pointed by ncoghlan. E.g.:

x, __ = func()

回答 5

三个简单的选择。

明显

x, _ = func()

x, junk = func()

可怕

x = func()[0]

并且有许多方法可以通过装饰器来实现。

def val0( aFunc ):
    def pick0( *args, **kw ):
        return aFunc(*args,**kw)[0]
    return pick0

func0= val0(func)

Three simple choices.

Obvious

x, _ = func()

x, junk = func()

Hideous

x = func()[0]

And there are ways to do this with a decorator.

def val0( aFunc ):
    def pick0( *args, **kw ):
        return aFunc(*args,**kw)[0]
    return pick0

func0= val0(func)

回答 6

最好的解决方案可能是命名事物,而不是返回无意义的元组。除非返回的项目的顺序背后有逻辑。

def func():
    return {'lat': 1, 'lng': 2}

latitude = func()['lat']

如果您想添加有关返回内容的更多信息,甚至可以使用namedtuple(不仅仅是字典,这些是坐标):

from collections import namedtuple 

Coordinates = namedtuple('Coordinates', ['lat', 'lng'])

def func():
    return Coordinates(lat=1, lng=2)

latitude = func().lat

如果字典/元组中的对象紧密地绑在一起,那么甚至最好为其定义一个类。这样,您还可以定义此类型对象之间的交互,并提供有关如何使用它们的API。接下来的自然问题是:什么时候应该在Python中使用类?

The best solution probably is to name things instead of returning meaningless tuples (unless there is some logic behind the order of the returned items). You can for example use a dictionary:

def func():
    return {'lat': 1, 'lng': 2}
    
latitude = func()['lat']

You could even use namedtuple if you want to add extra information about what you are returning (it’s not just a dictionary, it’s a pair of coordinates):

from collections import namedtuple 

Coordinates = namedtuple('Coordinates', ['lat', 'lng'])

def func():
    return Coordinates(lat=1, lng=2)

latitude = func().lat

If the objects within your dictionary/tuple are strongly tied together then it may be a good idea to even define a class for it. That way you’ll also be able to define more complex operations. A natural question that follows is: When should I be using classes in Python?

Most recent versions of python (≥ 3.7) have dataclasses which you can use to define classes with very few lines of code:

from dataclasses import dataclass

@dataclass
class Coordinates:
    lat: float = 0
    lng: float = 0

def func():
    return Coordinates(lat=1, lng=2)

latitude = func().lat

The primary advantage of dataclasses over namedtuple is that its easier to extend, but there are other differences. Note that by default, dataclasses are mutable, but you can use @dataclass(frozen=True) instead of @dataclass to force them being immutable.


回答 7

在我看来,这似乎是最佳选择:

val1, val2, ignored1, ignored2 = some_function()

它不是神秘的或丑陋的(就像func()[index]方法一样),并且清楚地说明了您的目的。

This seems like the best choice to me:

val1, val2, ignored1, ignored2 = some_function()

It’s not cryptic or ugly (like the func()[index] method), and clearly states your purpose.


回答 8

这不是问题的直接答案。而是回答了这个问题:“如何从许多可能的选项中选择特定的函数输出?”。

如果您能够编写该函数(即它不在库中,则无法修改),则添加一个输入自变量,以指示您要从该函数中获取的内容。将其设为具有默认值的命名参数,这样,在“普通情况”下,您甚至不必指定它。

    def fancy_function( arg1, arg2, return_type=1 ):
        ret_val = None
        if( 1 == return_type ):
            ret_val = arg1 + arg2
        elif( 2 == return_type ):
            ret_val = [ arg1, arg2, arg1 * arg2 ]
        else:
            ret_val = ( arg1, arg2, arg1 + arg2, arg1 * arg2 ) 
        return( ret_val )

该方法为所需的输出提供了“高级警告”功能。因此,它可以跳过不需要的处理,仅执行获得所需输出的必要工作。同样因为Python进行动态类型化,所以返回类型可以更改。请注意,示例如何返回标量,列表或元组……随您便!

This is not a direct answer to the question. Rather it answers this question: “How do I choose a specific function output from many possible options?”.

If you are able to write the function (ie, it is not in a library you cannot modify), then add an input argument that indicates what you want out of the function. Make it a named argument with a default value so in the “common case” you don’t even have to specify it.

    def fancy_function( arg1, arg2, return_type=1 ):
        ret_val = None
        if( 1 == return_type ):
            ret_val = arg1 + arg2
        elif( 2 == return_type ):
            ret_val = [ arg1, arg2, arg1 * arg2 ]
        else:
            ret_val = ( arg1, arg2, arg1 + arg2, arg1 * arg2 ) 
        return( ret_val )

This method gives the function “advanced warning” regarding the desired output. Consequently it can skip unneeded processing and only do the work necessary to get your desired output. Also because Python does dynamic typing, the return type can change. Notice how the example returns a scalar, a list or a tuple… whatever you like!


回答 9

如果这是您一直使用的函数,但始终舍弃第二个参数,那么我认为无需使用第二个返回值就可以为该函数创建别名不会太麻烦lambda

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 

If this is a function that you use all the time but always discard the second argument, I would argue that it is less messy to create an alias for the function without the second return value using lambda.

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 

回答 10

当您从一个函数获得许多输出并且不想多次调用它时,我认为选择结果的最简单方法是:

results = fct()
a,b = [results[i] for i in list_of_index]

作为最低限度的工作示例,还演示了该函数仅被调用一次:

def fct(a):
    b=a*2
    c=a+2
    d=a+b
    e=b*2
    f=a*a
    print("fct called")
    return[a,b,c,d,e,f]

results=fct(3)
> fct called

x,y = [results[i] for i in [1,4]]

和值是预期的:

results
> [3,6,5,9,12,9]
x
> 6
y
> 12

为了方便起见,还可以使用Python列表索引:

x,y = [results[i] for i in [0,-2]]

返回:a = 3和b = 12

When you have many output from a function and you don’t want to call it multiple times, I think the clearest way for selecting the results would be :

results = fct()
a,b = [results[i] for i in list_of_index]

As a minimum working example, also demonstrating that the function is called only once :

def fct(a):
    b=a*2
    c=a+2
    d=a+b
    e=b*2
    f=a*a
    print("fct called")
    return[a,b,c,d,e,f]

results=fct(3)
> fct called

x,y = [results[i] for i in [1,4]]

And the values are as expected :

results
> [3,6,5,9,12,9]
x
> 6
y
> 12

For convenience, Python list indexes can also be used :

x,y = [results[i] for i in [0,-2]]

Returns : a = 3 and b = 12


Python函数如何处理您传入的参数类型?

问题:Python函数如何处理您传入的参数类型?

除非我没有记错,否则在Python中创建函数的工作方式如下:

def my_func(param1, param2):
    # stuff

但是,您实际上并未提供这些参数的类型。另外,如果我记得,Python是一种强类型语言,因此,似乎Python不应让您传递与函数创建者所期望的类型不同的参数。但是,Python如何知道函数的用户正在传递正确的类型?假定函数实际上使用了参数,那么如果类型错误,程序会死掉吗?您必须指定类型吗?

Unless I’m mistaken, creating a function in Python works like this:

def my_func(param1, param2):
    # stuff

However, you don’t actually give the types of those parameters. Also, if I remember, Python is a strongly typed language, as such, it seems like Python shouldn’t let you pass in a parameter of a different type than the function creator expected. However, how does Python know that the user of the function is passing in the proper types? Will the program just die if it’s the wrong type, assuming the function actually uses the parameter? Do you have to specify the type?


回答 0

Python是强类型的,因为每个对象都有一个类型,每个对象都知道其类型,不可能无意或故意使用类型“好像”它是不同类型的对象,并且对该对象的所有基本操作都是委托给它的类型。

这与名称无关。Python中的名称没有“具有类型”:如果且在定义名称时,该名称指向一个对象,并且该对象确实具有一个类型(但实际上并不会强制该名称使用类型:名称是一个名称)。

Python中的名称可以很好地在不同时间引用不同的对象(就像在大多数编程语言中一样,尽管不是全部)-并且名称不受任何限制,因此,如果它曾经引用过X类型的对象,这样一来,便永远只能引用其他类型为X的对象。名称的约束不属于“强类型”概念的一部分,尽管一些静态类型的爱好者(名称确实受到约束,并且在静态AKA中会编译-时间,时尚也是如此)请勿以这种方式滥用该术语。

Python is strongly typed because every object has a type, every object knows its type, it’s impossible to accidentally or deliberately use an object of a type “as if” it was an object of a different type, and all elementary operations on the object are delegated to its type.

This has nothing to do with names. A name in Python doesn’t “have a type”: if and when a name’s defined, the name refers to an object, and the object does have a type (but that doesn’t in fact force a type on the name: a name is a name).

A name in Python can perfectly well refer to different objects at different times (as in most programming languages, though not all) — and there is no constraint on the name such that, if it has once referred to an object of type X, it’s then forevermore constrained to refer only to other objects of type X. Constraints on names are not part of the concept of “strong typing”, though some enthusiasts of static typing (where names do get constrained, and in a static, AKA compile-time, fashion, too) do misuse the term this way.


回答 1

其他答案在解释鸭子的类型和tzot的简单答案方面做得很好:

Python没有变量,就像其他语言一样,变量具有类型和值。它具有指向对象的名称,这些对象知道其类型。

但是,自2010年(首次提出该问题)以来,发生了一件有趣的事情,即PEP 3107的实现(在Python 3中实现)。现在,您实际上可以像这样指定参数的类型和函数的返回类型的类型:

def pick(l: list, index: int) -> int:
    return l[index]

我们在这里可以看到pick有两个参数,一个列表l和一个整数index。它还应该返回一个整数。

因此,这里暗示的l是一个整数列表,我们可以很轻松地看到它,但是对于更复杂的函数,该列表应包含的内容可能会有些混乱。我们还希望默认值为index0。要解决此问题,您可以选择这样写pick

def pick(l: "list of ints", index: int = 0) -> int:
    return l[index]

请注意,我们现在在字符串中添加了类型为的字符串l,这在语法上是允许的,但是对于以编程方式进行解析不是很好(我们将在后面介绍)。

重要的是要注意,TypeError如果将float传递给Python,Python不会引发index,这是Python设计哲学的主要观点之一:“我们都同意这里的成年人”,这意味着您应该注意可以传递给函数的内容以及不能传递给函数的内容。如果您确实想编写引发TypeErrors的代码,则可以使用该isinstance函数来检查所传递的参数是正确的类型还是其子类,如下所示:

def pick(l: list, index: int = 0) -> int:
    if not isinstance(l, list):
        raise TypeError
    return l[index]

下一部分和评论中将详细讨论为什么不应该这样做以及应该做什么。

PEP 3107不仅提高了代码的可读性,而且具有一些合适的用例,您可以在此处阅读。


随着PEP 484的引入,类型注释在Python 3.5中得到了更多的关注,PEP 484引入了用于类型提示的标准模块。

这些类型提示来自类型检查器mypyGitHub),它现在符合PEP 484

键入模块随附了非常全面的类型提示集合,包括:

  • ListTupleSetMap-为listtuplesetmap分别。
  • Iterable -对生成器有用。
  • Any -什么时候可以。
  • Union-相对于,它可以是指定类型集中的任何内容Any
  • Optional可能为“无”时。的简写Union[T, None]
  • TypeVar -与泛型一起使用。
  • Callable -主要用于函数,但可以用于其他可调用项。

这些是最常见的类型提示。可以在打字模块文档中找到完整的清单。

这是使用打字模块中引入的注释方法的旧示例:

from typing import List

def pick(l: List[int], index: int) -> int:
    return l[index]

一个强大的功能是Callable允许您键入将函数作为参数的注释方法。例如:

from typing import Callable, Any, Iterable

def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
    """An immediate version of map, don't pass it any infinite iterables!"""
    return list(map(f, l))

上面的示例可以通过使用TypeVar而不是来变得更加精确Any,但是这留给了读者练习,因为我相信我已经在答案中添加了有关类型提示所启用的出色新功能的过多信息。


以前,当编写一个带有Sphinx的文档化Python代码时,可以通过编写如下格式的文档字符串来获得上述某些功能:

def pick(l, index):
    """
    :param l: list of integers
    :type l: list
    :param index: index at which to pick an integer from *l*
    :type index: int
    :returns: integer at *index* in *l*
    :rtype: int
    """
    return l[index]

如您所见,这会花费很多额外的行(确切的行数取决于您想要的显式程度以及格式化文档字符串的方式)。但是,现在您应该清楚PEP 3107如何提供在许多(所有方式)方面都优越的替代方案。如我们所见,与PEP 484结合使用时尤其如此,如我们所见,PEP 484提供了一个标准模块,该模块定义了这些类型提示/注释的语法,该语法可以以明确,准确而灵活的方式使用,从而强大的组合。

我个人认为,这是Python上最伟大的功能之一。我等不及人们开始利用它的力量了。抱歉,答案很长,但是当我兴奋时就会发生这种情况。


此处可以找到大量使用类型提示的Python代码示例。

The other answers have done a good job at explaining duck typing and the simple answer by tzot:

Python does not have variables, like other languages where variables have a type and a value; it has names pointing to objects, which know their type.

However, one interesting thing has changed since 2010 (when the question was first asked), namely the implementation of PEP 3107 (implemented in Python 3). You can now actually specify the type of a parameter and the type of the return type of a function like this:

def pick(l: list, index: int) -> int:
    return l[index]

We can here see that pick takes 2 parameters, a list l and an integer index. It should also return an integer.

So here it is implied that l is a list of integers which we can see without much effort, but for more complex functions it can be a bit confusing as to what the list should contain. We also want the default value of index to be 0. To solve this you may choose to write pick like this instead:

def pick(l: "list of ints", index: int = 0) -> int:
    return l[index]

Note that we now put in a string as the type of l, which is syntactically allowed, but it is not good for parsing programmatically (which we’ll come back to later).

It is important to note that Python won’t raise a TypeError if you pass a float into index, the reason for this is one of the main points in Python’s design philosophy: “We’re all consenting adults here”, which means you are expected to be aware of what you can pass to a function and what you can’t. If you really want to write code that throws TypeErrors you can use the isinstance function to check that the passed argument is of the proper type or a subclass of it like this:

def pick(l: list, index: int = 0) -> int:
    if not isinstance(l, list):
        raise TypeError
    return l[index]

More on why you should rarely do this and what you should do instead is talked about in the next section and in the comments.

PEP 3107 does not only improve code readability but also has several fitting use cases which you can read about here.


Type annotation got a lot more attention in Python 3.5 with the introduction of PEP 484 which introduces a standard module for type hints.

These type hints came from the type checker mypy (GitHub), which is now PEP 484 compliant.

With the typing module comes with a pretty comprehensive collection of type hints, including:

  • List, Tuple, Set, Map – for list, tuple, set and map respectively.
  • Iterable – useful for generators.
  • Any – when it could be anything.
  • Union – when it could be anything within a specified set of types, as opposed to Any.
  • Optional – when it might be None. Shorthand for Union[T, None].
  • TypeVar – used with generics.
  • Callable – used primarily for functions, but could be used for other callables.

These are the most common type hints. A complete listing can be found in the documentation for the typing module.

Here is the old example using the annotation methods introduced in the typing module:

from typing import List

def pick(l: List[int], index: int) -> int:
    return l[index]

One powerful feature is the Callable which allows you to type annotate methods that take a function as an argument. For example:

from typing import Callable, Any, Iterable

def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
    """An immediate version of map, don't pass it any infinite iterables!"""
    return list(map(f, l))

The above example could become more precise with the usage of TypeVar instead of Any, but this has been left as an exercise to the reader since I believe I’ve already filled my answer with too much information about the wonderful new features enabled by type hinting.


Previously when one documented Python code with for example Sphinx some of the above functionality could be obtained by writing docstrings formatted like this:

def pick(l, index):
    """
    :param l: list of integers
    :type l: list
    :param index: index at which to pick an integer from *l*
    :type index: int
    :returns: integer at *index* in *l*
    :rtype: int
    """
    return l[index]

As you can see, this takes a number of extra lines (the exact number depends on how explicit you want to be and how you format your docstring). But it should now be clear to you how PEP 3107 provides an alternative that is in many (all?) ways superior. This is especially true in combination with PEP 484 which, as we have seen, provides a standard module that defines a syntax for these type hints/annotations that can be used in such a way that it is unambiguous and precise yet flexible, making for a powerful combination.

In my personal opinion, this is one of the greatest features in Python ever. I can’t wait for people to start harnessing the power of it. Sorry for the long answer, but this is what happens when I get excited.


An example of Python code which heavily uses type hinting can be found here.


回答 2

您没有指定类型。该方法仅在尝试访问传入的参数上未定义的属性时(运行时)失败。

所以这个简单的功能:

def no_op(param1, param2):
    pass

……无论传入什么两个参数,都不会失败。

但是,此功能:

def call_quack(param1, param2):
    param1.quack()
    param2.quack()

如果param1并且param2都不具有名为的可调用属性,则会在运行时失败quack

You don’t specify a type. The method will only fail (at runtime) if it tries to access attributes that are not defined on the parameters that are passed in.

So this simple function:

def no_op(param1, param2):
    pass

… will not fail no matter what two args are passed in.

However, this function:

def call_quack(param1, param2):
    param1.quack()
    param2.quack()

… will fail at runtime if param1 and param2 do not both have callable attributes named quack.


回答 3

许多语言都有变量,这些变量属于特定类型并具有值。Python没有变量。它具有对象,您可以使用名称来引用这些对象。

用其他语言,当您说:

a = 1

然后(通常为整数)变量将其内容更改为值1。

在Python中,

a = 1

表示“使用名称a引用对象1 ”。您可以在交互式Python会话中执行以下操作:

>>> type(1)
<type 'int'>

该函数type用对象调用1; 由于每个对象都知道其类型,因此很容易type找出所述类型并将其返回。

同样,无论何时定义函数

def funcname(param1, param2):

该函数接收两个对象,并为其命名为param1param2,无论它们的类型如何。如果要确保接收到的对象属于特定类型,请对函数进行编码,就好像它们属于所需的类型一样,并捕获不是的异常。引发的异常通常是TypeError(您使用了无效的操作)和AttributeError(您试图访问不存在的成员(方法也是成员))。

Many languages have variables, which are of a specific type and have a value. Python does not have variables; it has objects, and you use names to refer to these objects.

In other languages, when you say:

a = 1

then a (typically integer) variable changes its contents to the value 1.

In Python,

a = 1

means “use the name a to refer to the object 1”. You can do the following in an interactive Python session:

>>> type(1)
<type 'int'>

The function type is called with the object 1; since every object knows its type, it’s easy for type to find out said type and return it.

Likewise, whenever you define a function

def funcname(param1, param2):

the function receives two objects, and names them param1 and param2, regardless of their types. If you want to make sure the objects received are of a specific type, code your function as if they are of the needed type(s) and catch the exceptions that are thrown if they aren’t. The exceptions thrown are typically TypeError (you used an invalid operation) and AttributeError (you tried to access an inexistent member (methods are members too) ).


回答 4

在静态或编译时类型检查的意义上,Python的类型不是强类型。

大多数Python代码都属于所谓的 “ Duck Typing”鸭子输入) -例如,您read在对象上寻找一种方法-不在乎对象是磁盘上的文件还是套接字上的文件,您只想读N字节。

Python is not strongly typed in the sense of static or compile-time type checking.

Most Python code falls under so-called “Duck Typing” — for example, you look for a method read on an object — you don’t care if the object is a file on disk or a socket, you just want to read N bytes from it.


回答 5

正如Alex Martelli所说

正常的,Python式的首选解决方案几乎总是“鸭式输入”:尝试使用参数,就好像它是某个所需的类型一样,在try / except语句中进行操作,以捕获如果该参数实际上不是所有可能出现的异常该类型(或其他任何可以模仿它的类型;-),然后在except子句中尝试其他操作(使用参数“好像”它是其他类型)。

阅读他的文章的其余部分,以获取有用的信息。

As Alex Martelli explains,

The normal, Pythonic, preferred solution is almost invariably “duck typing”: try using the argument as if it was of a certain desired type, do it in a try/except statement catching all exceptions that could arise if the argument was not in fact of that type (or any other type nicely duck-mimicking it;-), and in the except clause, try something else (using the argument “as if” it was of some other type).

Read the rest of his post for helpful information.


回答 6

Python不在乎您将其传递给什么函数。当您调用时my_func(a,b),param1和param2变量将保存a和b的值。Python不知道您使用正确的类型来调用该函数,因此希望程序员来照顾好它。如果将使用不同类型的参数调用函数,则可以使用try / except块包装代码以访问它们,并以所需的任何方式评估参数。

Python doesn’t care what you pass in to its functions. When you call my_func(a,b), the param1 and param2 variables will then hold the values of a and b. Python doesn’t know that you are calling the function with the proper types, and expects the programmer to take care of that. If your function will be called with different types of parameters, you can wrap code accessing them with try/except blocks and evaluate the parameters in whatever way you want.


回答 7

您从不指定类型;Python具有鸭子类型的概念; 基本上,处理参数的代码将对它们做出某些假设-可能是通过调用期望参数实现的某些方法。如果参数的类型错误,则将引发异常。

通常,由代码决定是否传递正确类型的对象-没有编译器可以提前实施此类型。

You never specify the type; Python has the concept of duck typing; basically the code that processes the parameters will make certain assumptions about them – perhaps by calling certain methods that a parameter is expected to implement. If the parameter is of the wrong type, then an exception will be thrown.

In general it is up to your code to ensure that you are passing around objects of the proper type – there is no compiler to enforce this ahead of time.


回答 8

在这一页上,值得一提的是鸭子输入法,这是一个臭名昭著的exceptions。

str函数调用__str__类方法时,它会巧妙地改变其类型:

>>> class A(object):
...     def __str__(self):
...         return 'a','b'
...
>>> a = A()
>>> print a.__str__()
('a', 'b')
>>> print str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __str__ returned non-string (type tuple)

好像Guido提示我们程序遇到意外类型时应引发哪个异常。

There’s one notorious exception from the duck-typing worth mentioning on this page.

When str function calls __str__ class method it subtly сhecks its type:

>>> class A(object):
...     def __str__(self):
...         return 'a','b'
...
>>> a = A()
>>> print a.__str__()
('a', 'b')
>>> print str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __str__ returned non-string (type tuple)

As if Guido hints us which exception should a program raise if it encounters an unexpected type.


回答 9

在Python中,所有事物都有一个类型。如果参数类型支持它,Python函数将执行被要求执行的任何操作。

示例:foo将添加所有可以__add__编辑的内容;)不必担心其类型。因此,为了避免失败,您应该仅提供支持加法的那些东西。

def foo(a,b):
    return a + b

class Bar(object):
    pass

class Zoo(object):
    def __add__(self, other):
        return 'zoom'

if __name__=='__main__':
    print foo(1, 2)
    print foo('james', 'bond')
    print foo(Zoo(), Zoo())
    print foo(Bar(), Bar()) # Should fail

In Python everything has a type. A Python function will do anything it is asked to do if the type of arguments support it.

Example: foo will add everything that can be __add__ed ;) without worrying much about its type. So that means, to avoid failure, you should provide only those things that support addition.

def foo(a,b):
    return a + b

class Bar(object):
    pass

class Zoo(object):
    def __add__(self, other):
        return 'zoom'

if __name__=='__main__':
    print foo(1, 2)
    print foo('james', 'bond')
    print foo(Zoo(), Zoo())
    print foo(Bar(), Bar()) # Should fail

回答 10

我没有在其他答案中看到此内容,因此将其添加到锅中。

正如其他人所说的,Python并不对函数或方法参数强制执行类型。假定您知道自己在做什么,并且如果您确实需要知道传入的内容的类型,则将对其进行检查并决定自己要做什么。

isinstance()函数是执行此操作的主要工具之一。

例如,如果我编写的方法希望获取原始的二进制文本数据,而不是常规的utf-8编码的字符串,则可以检查途中的参数类型并适应我的发现,或者提高exceptions拒绝。

def process(data):
    if not isinstance(data, bytes) and not isinstance(data, bytearray):
        raise TypeError('Invalid type: data must be a byte string or bytearray, not %r' % type(data))
    # Do more stuff

Python还提供了各种工具来挖掘对象。如果您很勇敢,甚至可以使用importlib动态创建自己的任意类的对象。我这样做是为了从JSON数据重新创建对象。这样的事情对于像C ++这样的静态语言来说将是一场噩梦。

I didn’t see this mentioned in other answers, so I’ll add this to the pot.

As others have said, Python doesn’t enforce type on function or method parameters. It is assumed that you know what you’re doing, and that if you really need to know the type of something that was passed in, you will check it and decide what to do for yourself.

One of the main tools for doing this is the isinstance() function.

For example, if I write a method that expects to get raw binary text data, rather than the normal utf-8 encoded strings, I could check the type of the parameters on the way in and either adapt to what I find, or raise an exception to refuse.

def process(data):
    if not isinstance(data, bytes) and not isinstance(data, bytearray):
        raise TypeError('Invalid type: data must be a byte string or bytearray, not %r' % type(data))
    # Do more stuff

Python also provides all kinds of tools to dig into objects. If you’re brave, you can even use importlib to create your own objects of arbitrary classes, on the fly. I did this to recreate objects from JSON data. Such a thing would be a nightmare in a static language like C++.


回答 11

为了有效地使用键入模块(Python 3.5中的新增功能),请包括all(*)。

from typing import *

您将可以使用:

List, Tuple, Set, Map - for list, tuple, set and map respectively.
Iterable - useful for generators.
Any - when it could be anything.
Union - when it could be anything within a specified set of types, as opposed to Any.
Optional - when it might be None. Shorthand for Union[T, None].
TypeVar - used with generics.
Callable - used primarily for functions, but could be used for other callables.

但是,你仍然可以使用类的名称,如intlistdict,…

To effectively use the typing module (new in Python 3.5) include all (*).

from typing import *

And you will be ready to use:

List, Tuple, Set, Map - for list, tuple, set and map respectively.
Iterable - useful for generators.
Any - when it could be anything.
Union - when it could be anything within a specified set of types, as opposed to Any.
Optional - when it might be None. Shorthand for Union[T, None].
TypeVar - used with generics.
Callable - used primarily for functions, but could be used for other callables.

However, still you can use type names like int, list, dict,…


回答 12

如果有人想指定变量类型,我已经实现了包装器。

import functools

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for i in range(len(args)):
            v = args[i]
            v_name = list(func.__annotations__.keys())[i]
            v_type = list(func.__annotations__.values())[i]
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        v = result
        v_name = 'return'
        v_type = func.__annotations__['return']
        error_msg = 'Variable `' + str(v_name) + '` should be type ('
        error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
        if not isinstance(v, v_type):
                raise TypeError(error_msg)
        return result

    return check

用作:

@type_check
def test(name : str) -> float:
    return 3.0

@type_check
def test2(name : str) -> str:
    return 3.0

>> test('asd')
>> 3.0

>> test(42)
>> TypeError: Variable `name` should be type (<class 'str'>) but instead is type (<class 'int'>)

>> test2('asd')
>> TypeError: Variable `return` should be type (<class 'str'>) but instead is type (<class 'float'>)

编辑

如果未声明任何参数的类型(或返回值的类型),则以上代码将不起作用。另一方面,以下编辑可以提供帮助,它仅适用于kwargs,不检查args。

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for name, value in kwargs.items():
            v = value
            v_name = name
            if name not in func.__annotations__:
                continue

            v_type = func.__annotations__[name]

            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ') '
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        if 'return' in func.__annotations__:
            v = result
            v_name = 'return'
            v_type = func.__annotations__['return']
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                    raise TypeError(error_msg)
        return result

    return check

I have implemented a wrapper if anyone would like to specify variable types.

import functools
    
def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for i in range(len(args)):
            v = args[i]
            v_name = list(func.__annotations__.keys())[i]
            v_type = list(func.__annotations__.values())[i]
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        v = result
        v_name = 'return'
        v_type = func.__annotations__['return']
        error_msg = 'Variable `' + str(v_name) + '` should be type ('
        error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
        if not isinstance(v, v_type):
                raise TypeError(error_msg)
        return result

    return check

Use it as:

@type_check
def test(name : str) -> float:
    return 3.0

@type_check
def test2(name : str) -> str:
    return 3.0

>> test('asd')
>> 3.0

>> test(42)
>> TypeError: Variable `name` should be type (<class 'str'>) but instead is type (<class 'int'>)

>> test2('asd')
>> TypeError: Variable `return` should be type (<class 'str'>) but instead is type (<class 'float'>)

EDIT

The code above does not work if any of the arguments’ (or return’s) type is not declared. The following edit can help, on the other hand, it only works for kwargs and does not check args.

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for name, value in kwargs.items():
            v = value
            v_name = name
            if name not in func.__annotations__:
                continue
                
            v_type = func.__annotations__[name]

            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ') '
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        if 'return' in func.__annotations__:
            v = result
            v_name = 'return'
            v_type = func.__annotations__['return']
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                    raise TypeError(error_msg)
        return result

    return check


从命令行运行功能

问题:从命令行运行功能

我有以下代码:

def hello():
    return 'Hi :)'

我将如何直接从命令行运行它?

I have this code:

def hello():
    return 'Hi :)'

How would I run this directly from the command line?


回答 0

使用-c (command)参数(假设您的文件名为foo.py):

$ python -c 'import foo; print foo.hello()'

或者,如果您不关心命名空间污染,请执行以下操作:

$ python -c 'from foo import *; print hello()'

和中间立场:

$ python -c 'from foo import hello; print hello()'

With the -c (command) argument (assuming your file is named foo.py):

$ python -c 'import foo; print foo.hello()'

Alternatively, if you don’t care about namespace pollution:

$ python -c 'from foo import *; print hello()'

And the middle ground:

$ python -c 'from foo import hello; print hello()'

回答 1

只需将其hello()放在函数下方,它将在您执行时执行python your_file.py

对于更整洁的解决方案,您可以使用以下方法:

if __name__ == '__main__':
    hello()

这样,仅当您运行文件时才执行该功能,而不是在导入文件时执行该功能。

Just put hello() somewhere below the function and it will execute when you do python your_file.py

For a neater solution you can use this:

if __name__ == '__main__':
    hello()

That way the function will only be executed if you run the file, not when you import the file.


回答 2

python -c 'from myfile import hello; hello()'这里myfile必须使用Python脚本的基本名称来代替。(例如,myfile.py变为myfile)。

但是,如果hello()在您的Python脚本中是您的“永久”主入口点,那么执行此操作的通常方法如下:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

这样,您只需运行python myfile.py或即可执行脚本python -m myfile

此处的一些解释:__name__是一个特殊的Python变量,用于保存当前正在执行的模块的名称,除非从命令行启动模块(在这种情况下为)"__main__"

python -c 'from myfile import hello; hello()' where myfile must be replaced with the basename of your Python script. (E.g., myfile.py becomes myfile).

However, if hello() is your “permanent” main entry point in your Python script, then the usual way to do this is as follows:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

This allows you to execute the script simply by running python myfile.py or python -m myfile.

Some explanation here: __name__ is a special Python variable that holds the name of the module currently being executed, except when the module is started from the command line, in which case it becomes "__main__".


回答 3

我编写了一个快速的Python小脚本,可以从bash命令行调用它。它使用您要调用的模块,类和方法的名称以及您要传递的参数。我将其称为PyRun并保留了.py扩展名,并使其可用chmod + x PyRun可执行,因此我可以按如下所示快速调用它:

./PyRun PyTest.ClassName.Method1 Param1

将此保存在名为PyRun的文件中

#!/usr/bin/env python
#make executable in bash chmod +x PyRun

import sys
import inspect
import importlib
import os

if __name__ == "__main__":
    cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
    if cmd_folder not in sys.path:
        sys.path.insert(0, cmd_folder)

    # get the second argument from the command line      
    methodname = sys.argv[1]

    # split this into module, class and function name
    modulename, classname, funcname = methodname.split(".")

    # get pointers to the objects based on the string names
    themodule = importlib.import_module(modulename)
    theclass = getattr(themodule, classname)
    thefunc = getattr(theclass, funcname)

    # pass all the parameters from the third until the end of 
    # what the function needs & ignore the rest
    args = inspect.getargspec(thefunc)
    z = len(args[0]) + 2
    params=sys.argv[2:z]
    thefunc(*params)

这是一个示例模块,展示了它是如何工作的。这保存在名为PyTest.py的文件中:

class SomeClass:
 @staticmethod
 def First():
     print "First"

 @staticmethod
 def Second(x):
    print(x)
    # for x1 in x:
    #     print x1

 @staticmethod
 def Third(x, y):
     print x
     print y

class OtherClass:
    @staticmethod
    def Uno():
        print("Uno")

尝试运行以下示例:

./PyRun PyTest.SomeClass.First
./PyRun PyTest.SomeClass.Second Hello
./PyRun PyTest.SomeClass.Third Hello World
./PyRun PyTest.OtherClass.Uno
./PyRun PyTest.SomeClass.Second "Hello"
./PyRun PyTest.SomeClass.Second \(Hello, World\)

请注意最后一个转义括号以将元组作为Second方法的唯一参数传递的示例。

如果为该方法所需的参数传递的参数太少,则会出现错误。如果您通过太多,它将忽略额外费用。该模块必须在当前工作文件夹中,将PyRun放置在路径中的任何位置。

I wrote a quick little Python script that is callable from a bash command line. It takes the name of the module, class and method you want to call and the parameters you want to pass. I call it PyRun and left off the .py extension and made it executable with chmod +x PyRun so that I can just call it quickly as follow:

./PyRun PyTest.ClassName.Method1 Param1

Save this in a file called PyRun

#!/usr/bin/env python
#make executable in bash chmod +x PyRun

import sys
import inspect
import importlib
import os

if __name__ == "__main__":
    cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
    if cmd_folder not in sys.path:
        sys.path.insert(0, cmd_folder)

    # get the second argument from the command line      
    methodname = sys.argv[1]

    # split this into module, class and function name
    modulename, classname, funcname = methodname.split(".")

    # get pointers to the objects based on the string names
    themodule = importlib.import_module(modulename)
    theclass = getattr(themodule, classname)
    thefunc = getattr(theclass, funcname)

    # pass all the parameters from the third until the end of 
    # what the function needs & ignore the rest
    args = inspect.getargspec(thefunc)
    z = len(args[0]) + 2
    params=sys.argv[2:z]
    thefunc(*params)

Here is a sample module to show how it works. This is saved in a file called PyTest.py:

class SomeClass:
 @staticmethod
 def First():
     print "First"

 @staticmethod
 def Second(x):
    print(x)
    # for x1 in x:
    #     print x1

 @staticmethod
 def Third(x, y):
     print x
     print y

class OtherClass:
    @staticmethod
    def Uno():
        print("Uno")

Try running these examples:

./PyRun PyTest.SomeClass.First
./PyRun PyTest.SomeClass.Second Hello
./PyRun PyTest.SomeClass.Third Hello World
./PyRun PyTest.OtherClass.Uno
./PyRun PyTest.SomeClass.Second "Hello"
./PyRun PyTest.SomeClass.Second \(Hello, World\)

Note the last example of escaping the parentheses to pass in a tuple as the only parameter to the Second method.

If you pass too few parameters for what the method needs you get an error. If you pass too many, it ignores the extras. The module must be in the current working folder, put PyRun can be anywhere in your path.


回答 4

将此代码段添加到脚本的底部

def myfunction():
    ...


if __name__ == '__main__':
    globals()[sys.argv[1]]()

您现在可以通过运行来调用函数

python myscript.py myfunction

之所以有效,是因为您要将命令行参数(函数名称的字符串)传递给locals,该字典具有当前本地符号表。最后的括号将使函数被调用。

更新:如果您希望函数从命令行接受参数,则可以这样传递sys.argv[2]

def myfunction(mystring):
    print mystring


if __name__ == '__main__':
    globals()[sys.argv[1]](sys.argv[2])

这样,运行python myscript.py myfunction "hello"将输出hello

add this snippet to the bottom of your script

def myfunction():
    ...


if __name__ == '__main__':
    globals()[sys.argv[1]]()

You can now call your function by running

python myscript.py myfunction

This works because you are passing the command line argument (a string of the function’s name) into locals, a dictionary with a current local symbol table. The parantheses at the end will make the function be called.

update: if you would like the function to accept a parameter from the command line, you can pass in sys.argv[2] like this:

def myfunction(mystring):
    print mystring


if __name__ == '__main__':
    globals()[sys.argv[1]](sys.argv[2])

This way, running python myscript.py myfunction "hello" will output hello.


回答 5

让我们自己简化一点,只使用一个模块…

尝试: pip install compago

然后写:

import compago
app = compago.Application()

@app.command
def hello():
    print "hi there!"

@app.command
def goodbye():
    print "see ya later."

if __name__ == "__main__":
    app.run()

然后像这样使用:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

注意:目前Python 3中存在一个错误,但与Python 2配合使用时效果很好。

编辑:我认为是一个更好的选择,是Google 触发的模块,这也使得传递函数参数变得容易。它与一起安装pip install fire。从他们的GitHub:

这是一个简单的例子。

import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

然后,可以从命令行运行:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30

Let’s make this a little easier on ourselves and just use a module…

Try: pip install compago

Then write:

import compago
app = compago.Application()

@app.command
def hello():
    print "hi there!"

@app.command
def goodbye():
    print "see ya later."

if __name__ == "__main__":
    app.run()

Then use like so:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Note: There’s a bug in Python 3 at the moment, but works great with Python 2.

Edit: An even better option, in my opinion is the module fire by Google which makes it easy to also pass function arguments. It is installed with pip install fire. From their GitHub:

Here’s a simple example.

import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

Then, from the command line, you can run:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30

回答 6

有趣的是,如果目标是打印到命令行控制台或执行其他一些分钟的python操作,则可以将输入通过管道传递到python解释器中,如下所示:

echo print("hi:)") | python

以及管道文件

python < foo.py

*请注意,扩展名不必一定是.py才能正常工作。**还请注意,对于bash而言,您可能需要转义字符

echo print\(\"hi:\)\"\) | python

Interestingly enough, if the goal was to print to the command line console or perform some other minute python operation, you can pipe input into the python interpreter like so:

echo print("hi:)") | python

as well as pipe files..

python < foo.py

*Note that the extension does not have to be .py for the second to work. **Also note that for bash you may need to escape the characters

echo print\(\"hi:\)\"\) | python

回答 7

如果安装runp软件包时pip install runp需要运行:

runp myfile.py hello

您可以在以下位置找到存储库:https : //github.com/vascop/runp

If you install the runp package with pip install runp its a matter of running:

runp myfile.py hello

You can find the repository at: https://github.com/vascop/runp


回答 8

我需要在命令行上使用各种python实用程序(范围,字符串等),并为此专门编写了pyfunc工具。您可以使用它来丰富您的命令行使用经验:

 $ pyfunc -m range -a 1 7 2
 1
 3
 5

 $ pyfunc -m string.upper -a test
 TEST

 $ pyfunc -m string.replace -a 'analyze what' 'what' 'this'
 analyze this

I had a requirement of using various python utilities (range, string, etc.) on the command line and had written the tool pyfunc specifically for that. You can use it to enrich you command line usage experience:

 $ pyfunc -m range -a 1 7 2
 1
 3
 5

 $ pyfunc -m string.upper -a test
 TEST

 $ pyfunc -m string.replace -a 'analyze what' 'what' 'this'
 analyze this

回答 9

始终可以使用python命令在命令行中输入python

然后导入您的文件,以便导入example_file

然后使用example_file.hello()运行命令

这避免了每次运行python -c等时都会出现的怪异.pyc复制函数。

也许不像单个命令那样方便,但是它是一个很好的快速修复程序,可从命令行向文件发送文本,并允许您使用python来调用和执行文件。

It is always an option to enter python on the command line with the command python

then import your file so import example_file

then run the command with example_file.hello()

This avoids the weird .pyc copy function that crops up every time you run python -c etc.

Maybe not as convenient as a single-command, but a good quick fix to text a file from the command line, and allows you to use python to call and execute your file.


回答 10

像这样:call_from_terminal.py

# call_from_terminal.py
# Ex to run from terminal
# ip='"hi"'
# python -c "import call_from_terminal as cft; cft.test_term_fun(${ip})"
# or
# fun_name='call_from_terminal'
# python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
def test_term_fun(ip):
    print ip

这在bash中有效。

$ ip='"hi"' ; fun_name='call_from_terminal' 
$ python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
hi

Something like this: call_from_terminal.py

# call_from_terminal.py
# Ex to run from terminal
# ip='"hi"'
# python -c "import call_from_terminal as cft; cft.test_term_fun(${ip})"
# or
# fun_name='call_from_terminal'
# python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
def test_term_fun(ip):
    print ip

This works in bash.

$ ip='"hi"' ; fun_name='call_from_terminal' 
$ python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
hi

回答 11

下面是Odd_Even_function.py文件,其中包含函数的定义。

def OE(n):
    for a in range(n):
        if a % 2 == 0:
            print(a)
        else:
            print(a, "ODD")

现在,从下面的命令提示符处调用相同的选项对我有用。

选项1 exe \ python.exe -c“导入Odd_Even_function; Odd_Even_function.OE(100)”的完整路径

选项2 exe \ python.exe -c“从Odd_Even_function import OE; OE(100)”的完整路径

谢谢。

Below is the Odd_Even_function.py file that has the definition of the function.

def OE(n):
    for a in range(n):
        if a % 2 == 0:
            print(a)
        else:
            print(a, "ODD")

Now to call the same from Command prompt below are the options worked for me.

Options 1 Full path of the exe\python.exe -c “import Odd_Even_function; Odd_Even_function.OE(100)”

Option 2 Full path of the exe\python.exe -c “from Odd_Even_function import OE; OE(100)”

Thanks.


回答 12

此函数无法从命令行运行,因为它返回的值将不可用。您可以删除退货并改为使用打印

This function cannot be run from the command line as it returns a value which will go unhanded. You can remove the return and use print instead


回答 13

使用python-c工具(pip install python-c),然后简单地编写:

$ python-c foo 'hello()'

或在python文件中没有函数名冲突的情况下:

$ python-c 'hello()'

Use the python-c tool (pip install python-c) and then simply write:

$ python-c foo 'hello()'

or in case you have no function name clashes in your python files:

$ python-c 'hello()'

回答 14

首先,您必须按照他们告诉您的方式调用该函数,否则该功能将在输出中不显示任何内容,之后保存文件并通过右键单击将文件的路径复制到文件的文件夹,然后单击“复制文件”转到终端并输入:-cd“文件的路径”-python“例如文件的名称(main.py)”,之后它将显示代码的输出。

First you have to call the function as they told you or the founction will display nothing in the output, after that save the file and copy the path of the file by right click to the folder of the file and click on”copy file” then go to terminal and write: – cd “the path of the file” – python “name of the file for example (main.py)” after that it will display the output of your code.


回答 15

安装Spyder,让您的生活更轻松。打开文件,然后运行它(单击绿色箭头)。之后,您的hello()方法已定义并为IPython控制台所知,因此您可以从控制台中调用它。

Make your life easier, install Spyder. Open your file then run it (click the green arrow). Afterwards your hello() method is defined and known to the IPython Console, so you can call it from the console.


将字典作为关键字参数传递给函数

问题:将字典作为关键字参数传递给函数

我想使用字典在python中调用一个函数。

这是一些代码:

d = dict(param='test')

def f(param):
    print(param)

f(d)

这可以打印,{'param': 'test'}但我希望只打印test

我希望它可以类似地工作以获取更多参数:

d = dict(p1=1, p2=2)
def f2(p1, p2):
    print(p1, p2)
f2(d)

这可能吗?

I’d like to call a function in python using a dictionary.

Here is some code:

d = dict(param='test')

def f(param):
    print(param)

f(d)

This prints {'param': 'test'} but I’d like it to just print test.

I’d like it to work similarly for more parameters:

d = dict(p1=1, p2=2)
def f2(p1, p2):
    print(p1, p2)
f2(d)

Is this possible?


回答 0

最后自己解决了。很简单,我只是缺少**运算符来解开字典

因此,我的示例变为:

d = dict(p1=1, p2=2)
def f2(p1,p2):
    print p1, p2
f2(**d)

Figured it out for myself in the end. It is simple, I was just missing the ** operator to unpack the dictionary

So my example becomes:

d = dict(p1=1, p2=2)
def f2(p1,p2):
    print p1, p2
f2(**d)

回答 1

In[1]: def myfunc(a=1, b=2):
In[2]:    print(a, b)

In[3]: mydict = {'a': 100, 'b': 200}

In[4]: myfunc(**mydict)
100 200

一些可能有助于了解的其他详细信息(阅读本文并经过测试后遇到的问题):

  1. 该函数可以具有字典中包含的参数
  2. 不能覆盖字典中已经存在的参数
  3. 字典不能包含函数中没有的参数。

例子:

数字1:该函数可以具有字典中未包含的参数

In[5]: mydict = {'a': 100}
In[6]: myfunc(**mydict)
100 2

数字2:您不能覆盖字典中已经存在的参数

In[7]: mydict = {'a': 100, 'b': 200}
In[8]: myfunc(a=3, **mydict)

TypeError: myfunc() got multiple values for keyword argument 'a'

数字3:字典中不能包含函数中没有的参数。

In[9]:  mydict = {'a': 100, 'b': 200, 'c': 300}
In[10]: myfunc(**mydict)

TypeError: myfunc() got an unexpected keyword argument 'c'

根据注释中的要求,第3号的解决方案是根据函数中可用的关键字参数来过滤字典:

In[11]: import inspect
In[12]: mydict = {'a': 100, 'b': 200, 'c': 300}
In[13]: filtered_mydict = {k: v for k, v in mydict.items() if k in [p.name for p in inspect.signature(myfunc).parameters.values()]}
In[14]: myfunc(**filtered_mydict)
100 200

另一种选择是在函数中接受(并忽略)其他kwarg:

In[15]: def myfunc2(a=None, **kwargs):
In[16]:    print(a)

In[17]: mydict = {'a': 100, 'b': 200, 'c': 300}

In[18]: myfunc2(**mydict)
100

请注意,除了可以有效地使用位置参数和列表或元组之外,还可以使用与kwargs相同的方式,这是一个更高级的示例,其中同时包含位置和关键字args:

In[19]: def myfunc3(a, *posargs, b=2, **kwargs):
In[20]:    print(a, b)
In[21]:    print(posargs)
In[22]:    print(kwargs)

In[23]: mylist = [10, 20, 30]
In[24]: mydict = {'b': 200, 'c': 300}

In[25]: myfunc3(*mylist, **mydict)
10 200
(20, 30)
{'c': 300}
In[1]: def myfunc(a=1, b=2):
In[2]:    print(a, b)

In[3]: mydict = {'a': 100, 'b': 200}

In[4]: myfunc(**mydict)
100 200

A few extra details that might be helpful to know (questions I had after reading this and went and tested):

  1. The function can have parameters that are not included in the dictionary
  2. You can not override a parameter that is already in the dictionary
  3. The dictionary can not have parameters that aren’t in the function.

Examples:

Number 1: The function can have parameters that are not included in the dictionary

In[5]: mydict = {'a': 100}
In[6]: myfunc(**mydict)
100 2

Number 2: You can not override a parameter that is already in the dictionary

In[7]: mydict = {'a': 100, 'b': 200}
In[8]: myfunc(a=3, **mydict)

TypeError: myfunc() got multiple values for keyword argument 'a'

Number 3: The dictionary can not have parameters that aren’t in the function.

In[9]:  mydict = {'a': 100, 'b': 200, 'c': 300}
In[10]: myfunc(**mydict)

TypeError: myfunc() got an unexpected keyword argument 'c'

As requested in comments, a solution to Number 3 is to filter the dictionary based on the keyword arguments available in the function:

In[11]: import inspect
In[12]: mydict = {'a': 100, 'b': 200, 'c': 300}
In[13]: filtered_mydict = {k: v for k, v in mydict.items() if k in [p.name for p in inspect.signature(myfunc).parameters.values()]}
In[14]: myfunc(**filtered_mydict)
100 200

Another option is to accept (and ignore) additional kwargs in your function:

In[15]: def myfunc2(a=None, **kwargs):
In[16]:    print(a)

In[17]: mydict = {'a': 100, 'b': 200, 'c': 300}

In[18]: myfunc2(**mydict)
100

Notice further than you can use positional arguments and lists or tuples in effectively the same way as kwargs, here’s a more advanced example incorporating both positional and keyword args:

In[19]: def myfunc3(a, *posargs, b=2, **kwargs):
In[20]:    print(a, b)
In[21]:    print(posargs)
In[22]:    print(kwargs)

In[23]: mylist = [10, 20, 30]
In[24]: mydict = {'b': 200, 'c': 300}

In[25]: myfunc3(*mylist, **mydict)
10 200
(20, 30)
{'c': 300}

回答 2

在python中,这称为“拆包”,您​​可以在本教程中找到有关它的信息。我同意,它的文档很烂,尤其是因为它是如此的有用。

In python, this is called “unpacking”, and you can find a bit about it in the tutorial. The documentation of it sucks, I agree, especially because of how fantasically useful it is.


回答 3

在这里-可以进行其他任何迭代:

d = {'param' : 'test'}

def f(dictionary):
    for key in dictionary:
        print key

f(d)

Here ya go – works just any other iterable:

d = {'param' : 'test'}

def f(dictionary):
    for key in dictionary:
        print key

f(d)

从Python中的另一个文件调用函数

问题:从Python中的另一个文件调用函数

设置:我需要在程序中使用每个函数的.py文件。

在此程序中,我需要从外部文件调用该函数。

我试过了:

from file.py import function(a,b)

但是我得到了错误:

ImportError:没有名为“ file.py”的模块;文件不是包

我该如何解决这个问题?

Set_up: I have a .py file for each function I need to use in a program.

In this program, I need to call the function from the external files.

I’ve tried:

from file.py import function(a,b)

But I get the error:

ImportError: No module named ‘file.py’; file is not a package

How do I fix this problem?


回答 0

file.py导入时无需添加任何内容。只需编写from file import function,然后使用调用函数function(a, b)。之所以可能不起作用,是因为它file是Python的核心模块之一,所以我建议您更改文件名。

请注意,如果您尝试将函数从导入a.py到名为的文件中b.py,则需要确保a.pyb.py处于同一目录中。

There isn’t any need to add file.py while importing. Just write from file import function, and then call the function using function(a, b). The reason why this may not work, is because file is one of Python’s core modules, so I suggest you change the name of your file.

Note that if you’re trying to import functions from a.py to a file called b.py, you will need to make sure that a.py and b.py are in the same directory.


回答 1

首先,您不需要.py

如果您有文件a.py并且内部有一些功能:

def b():
  # Something
  return 1

def c():
  # Something
  return 2

而您要导入它们,z.py您必须编写

from a import b, c

First of all you do not need a .py.

If you have a file a.py and inside you have some functions:

def b():
  # Something
  return 1

def c():
  # Something
  return 2

And you want to import them in z.py you have to write

from a import b, c

回答 2

您可以通过2种方式执行此操作。首先只是从file.py导入所需的特定功能。为此使用

from file import function

另一种方法是导入整个文件

import file as fl

然后您可以使用以下命令在file.py中调用任何函数

fl.function(a,b)

You can do this in 2 ways. First is just to import the specific function you want from file.py. To do this use

from file import function

Another way is to import the entire file

import file as fl

Then you can call any function inside file.py using

fl.function(a,b)

回答 3

如果您不能或不想在正在使用的同一目录中使用该函数,也可以从其他目录中调用该函数。您可以通过两种方式来做到这一点(也许还有更多选择,但这是对我有用的选择)。

备选方案1临时更改您的工作目录

import os

os.chdir("**Put here the directory where you have the file with your function**")

from file import function

os.chdir("**Put here the directory where you were working**")

选择2将具有功能的目录添加到sys.path

import sys

sys.path.append("**Put here the directory where you have the file with your function**")

from file import function

You can call the function from a different directory as well, in case you cannot or do not want to have the function in the same directory you are working. You can do this in two ways (perhaps there are more alternatives, but these are the ones that have worked for me).

Alternative 1 Temporarily change your working directory

import os

os.chdir("**Put here the directory where you have the file with your function**")

from file import function

os.chdir("**Put here the directory where you were working**")

Alternative 2 Add the directory where you have your function to sys.path

import sys

sys.path.append("**Put here the directory where you have the file with your function**")

from file import function

回答 4

如果您的文件位于不同的包结构中,并且您想从其他包中调用它,则可以按照以下方式调用它:

假设您在python项目中具有以下包结构:

com.my.func.DifferentFunction-python文件中,您具有一些功能,例如:

def add(arg1, arg2):
    return arg1 + arg2

def sub(arg1, arg2) :
    return arg1 - arg2

def mul(arg1, arg2) :
    return arg1 * arg2

您想从中调用不同的函数Example3.py,然后按照以下方式进行操作:

Example3.py文件中定义导入语句以导入所有功能

from com.my.func.DifferentFunction import *

或定义要导入的每个函数名称

from com.my.func.DifferentFunction import add, sub, mul

然后Example3.py可以调用函数执行:

num1 = 20
num2 = 10

print("\n add : ", add(num1,num2))
print("\n sub : ", sub(num1,num2))
print("\n mul : ", mul(num1,num2))

输出:

 add :  30

 sub :  10

 mul :  200

If your file is in the different package structure and you want to call it from a different package, then you can call it in that fashion:

Let’s say you have following package structure in your python project:

in – com.my.func.DifferentFunction python file you have some function, like:

def add(arg1, arg2):
    return arg1 + arg2

def sub(arg1, arg2) :
    return arg1 - arg2

def mul(arg1, arg2) :
    return arg1 * arg2

And you want to call different functions from Example3.py, then following way you can do it:

Define import statement in Example3.py – file for import all function

from com.my.func.DifferentFunction import *

or define each function name which you want to import

from com.my.func.DifferentFunction import add, sub, mul

Then in Example3.py you can call function for execute:

num1 = 20
num2 = 10

print("\n add : ", add(num1,num2))
print("\n sub : ", sub(num1,num2))
print("\n mul : ", mul(num1,num2))

Output:

 add :  30

 sub :  10

 mul :  200

回答 5

遇到了相同的功能,但我必须执行以下操作才能使其正常工作。

如果看到“ ModuleNotFoundError:未命名模块”,则可能需要在文件名前面加点号(。),如下所示;

.file导入功能

Came across the same feature but I had to do the below to make it work.

If you are seeing ‘ModuleNotFoundError: No module named’, you probably need the dot(.) in front of the filename as below;

from .file import funtion


回答 6

首先以.py格式保存文件(例如my_example.py)。如果该文件具有功能,

def xyz():

        --------

        --------

def abc():

        --------

        --------

在调用函数中,您只需要键入以下几行。

文件名:my_example2.py

===========================

import my_example.py


a = my_example.xyz()

b = my_example.abc()

===========================

First save the file in .py format (for example, my_example.py). And if that file have functions,

def xyz():

        --------

        --------

def abc():

        --------

        --------

In the calling function you just have to type the below lines.

file_name: my_example2.py

============================

import my_example.py


a = my_example.xyz()

b = my_example.abc()

============================


回答 7

将模块重命名为“文件”以外的名称。

然后还要确保在调用函数时:

1)如果要导入整个模块,则在调用它时要重申模块名称:

import module
module.function_name()

要么

import pizza
pizza.pizza_function()

2)或如果您要导入特定功能,带别名的功能或所有使用*的功能,则无需重复模块名称:

from pizza import pizza_function
pizza_function()

要么

from pizza import pizza_function as pf
pf()

要么

from pizza import *
pizza_function()

Rename the module to something other than ‘file’.

Then also be sure when you are calling the function that:

1)if you are importing the entire module, you reiterate the module name when calling it:

import module
module.function_name()

or

import pizza
pizza.pizza_function()

2)or if you are importing specific functions, functions with an alias, or all functions using *, you don’t reiterate the module name:

from pizza import pizza_function
pizza_function()

or

from pizza import pizza_function as pf
pf()

or

from pizza import *
pizza_function()

回答 8

.py文件中的函数(可以(当然)可以在不同目录中)可以通过首先写入目录然后输入不带.py扩展名的文件名来简单地导入:

from directory_name.file_name import function_name

后来被使用: function_name()

Functions from .py file (can (of course) be in different directory) can be simply imported by writing directories first and then the file name without .py extension:

from directory_name.file_name import function_name

And later be used: function_name()


回答 9

在MathMethod.Py内部。

def Add(a,b):
   return a+b 

def subtract(a,b):
  return a-b

内部Main.Py

import MathMethod as MM 
  print(MM.Add(200,1000))

输出:1200

Inside MathMethod.Py.

def Add(a,b):
   return a+b 

def subtract(a,b):
  return a-b

Inside Main.Py

import MathMethod as MM 
  print(MM.Add(200,1000))

Output:1200


回答 10

您不必添加file.py

只需将文件与文件导入位置保持在相同位置即可。然后只需导入您的函数:

from file import a, b

You don’t have to add file.py.

Just keep the file in the same location with the file from where you want to import it. Then just import your functions:

from file import a, b

回答 11

您应该将文件与要导入的Python文件放在同一位置。“从文件导入功能”也足够。

You should have the file at the same location as that of the Python files you are trying to import. Also ‘from file import function’ is enough.


回答 12

如果要导入此文件,请在文件名前附加一个点(。),该文件与运行代码的目录相同。

例如,我正在运行一个名为a.py的文件,我想导入一个名为addFun的方法,该方法是用b.py编写的,而b.py在同一目录中

从.b import addFun

append a dot(.) in front of a file name if you want to import this file which is in the same directory where you are running your code.

For example, i’m running a file named a.py and i want to import a method named addFun which is written in b.py, and b.py is there in the same directory

from .b import addFun


回答 13

假设您要调用的文件是anotherfile.py,并且您要调用的方法是method1,然后先导入文件,然后再导入方法

from anotherfile import method1

如果method1是类的一部分,则将该类设为class1,则

from anotherfile import class1

然后创建一个class1对象,假设对象名称是ob1,然后

ob1 = class1()
ob1.method1()

Suppose the file you want to call is anotherfile.py and the method you want to call is method1, then first import the file and then the method

from anotherfile import method1

if method1 is part of a class, let the class be class1, then

from anotherfile import class1

then create an object of class1, suppose the object name is ob1, then

ob1 = class1()
ob1.method1()

回答 14

就我而言,我命名了文件helper.scrap.py,直到更改为helper.py

in my case i named my file helper.scrap.py and couldn’t make it work until i changed to helper.py