简体   繁体   English

如何通过(字符串)名称 select 变量?

[英]How can I select a variable by (string) name?

I want to return a pre-determined list from my function, based on the string input.我想根据字符串输入从我的 function 返回一个预先确定的列表。

def get_ext(file_type):
    text = ['txt', 'doc']
    audio = ['mp3', 'wav']
    video = ['mp4', 'mkv']
    return # what do I return here?

get_ext('audio')  #should return the list ['mp3', 'wav']

What is the easiest way to do it?最简单的方法是什么?


For the related problem of trying to use strings to assign or create variables, see How do I create variable variables?关于尝试使用字符串赋值或创建变量的相关问题,请参见如何创建变量变量? . . This question is about looking them up.这个问题是关于查找它们的。

In most cases like this, an ordinary dictionary will do the job just fine.在大多数情况下,普通的字典就可以完成这项工作。

>>> get_ext = {'text': ['txt', 'doc'],
...            'audio': ['mp3', 'wav'],
...            'video': ['mp4', 'mkv']
... }
>>> 
>>> get_ext['video']
['mp4', 'mkv']

If you really want or need a function (for which there can be valid reasons) you have a couple of options.如果您真的想要或需要一个功能(可能有正当理由),您有几个选择。 One of the easiest is to assign to the get method of the dictionary.最简单的方法之一是分配给字典的get方法。 You can even re-assign the name get_ext if you don't have use for the dictionary behind the curtain.如果您不使用幕后的字典,您甚至可以重新分配名称get_ext

>>> get_ext = get_ext.get
>>> get_ext('video')
['mp4', 'mkv']

This function will return None per default if you enter an unknown key:如果您输入未知键,此函数将默认返回None

>>> x = get_ext('binary')
>>> x is None
True

If you want a KeyError instead for unknown keys, assign to get_ext.__getitem__ instead of get_ext.get .如果您想要KeyError而不是未知键,请分配给get_ext.__getitem__而不是get_ext.get

If you want a custom default-value one approach is to wrap the dictionary inside a function.如果您想要自定义默认值,一种方法是将字典包装在函数中。 This example uses an empty list as the default value.此示例使用空列表作为默认值。

def get_ext(file_type):
    types = {'text': ['txt', 'doc'],
             'audio': ['mp3', 'wav'],
             'video': ['mp4', 'mkv']
    }

    return types.get(file_type, [])

However, @omri_saadon gave the valid remark that the types = ... assignment is performed every function call.但是,@omri_saadon 给出了有效的评论,即types = ...分配在每个函数调用中执行。 Here's what you can do to get around that if this bothers you.如果这让您感到困扰,您可以采取以下措施来解决这个问题。

class get_ext(object):
    def __init__(self):
        self.types = {'text': ['txt', 'doc'],
                      'audio': ['mp3', 'wav'],
                      'video': ['mp4', 'mkv']
        }

    def __call__(self, file_type):
        return self.types.get(file_type, [])

get_ext = get_ext()

You can use get_ext like a regular function from here on, because in the end callables are callables.从这里开始,您可以像使用常规函数一样使用get_ext ,因为最终可调用对象是可调用对象。 :) :)

Note that this approach - besides the fact that self.types is only created once - has the considerable advantage that you can still easily change the file types your function recognizes.请注意,这种方法 - 除了self.types仅创建一次这一事实之外 - 具有相当大的优势,您仍然可以轻松更改函数识别的文件类型。

>>> get_ext.types['binary'] = ['bin', 'exe']
>>> get_ext('binary')
['bin', 'exe']

If you don't want to define a dictionary as in @timgeb's answer , then you can call locals() , which gives you a dict of the variables available in the local scope.如果您不@timgeb's answer那样定义dictionary ,那么您可以调用locals() ,它会为您提供本地范围内可用变量的dict

def get_ext(file_type):
    text = ['txt', 'doc']
    audio = ['mp3', 'wav']
    video = ['mp4', 'mkv']
    return locals()[file_type]

and a test to show it works:并进行测试以证明其有效:

>>> get_ext("text")
['txt', 'doc']

You can easily use dict with tuple/list values like so:您可以轻松地将 dict 与元组/列表值一起使用,如下所示:

def get_ext(file_type):
    d = {'text': ['txt', 'doc'],
         'audio': ['mp3', 'wav'],
         'video': ['mp4', 'mkv']}
    return d[file_type]


print(get_ext('audio'))

Use dictionary:使用字典:

def get_ext(file_type):
    d = {'text' : ['txt', 'doc'],
         'audio' : ['mp3', 'wav'],
         'video' : ['mp4', 'mkv']}
    try:
        return d[file_type]
    except KeyError:
        return []

get_ext('audio') # ['mp3', 'wav']

returns empty list in case that key does not exists.如果该键不存在,则返回空列表。 how ever this is simplest answer that came in my mind , for better answer see @timgeb answer.这是我想到的最简单的答案,要获得更好的答案,请参阅@timgeb 答案。

As per the answer by @timgeb I'd use a dictionary, but if you're accessing a lot, care about speed and don't want to define a class you can use caching.根据@timgeb 的回答,我会使用字典,但是如果您访问很多,请关心速度并且不想定义可以使用缓存的类。

from functools import lru_cache

def get_ext(file_type):
    d = {'text': ['txt', 'doc'],
         'audio': ['mp3', 'wav'],
         'video': ['mp4', 'mkv']}
    return d[file_type]

@lru_cache(maxsize=3, typed=False)
def get_ext_cached(file_type):
    d = {'text': ['txt', 'doc'],
         'audio': ['mp3', 'wav'],
         'video': ['mp4', 'mkv']}
    return d[file_type]

from timeit import timeit

# non cached
print(timeit(stmt='get_ext("text")', globals={'get_ext': get_ext}))
# 0.48447531609922706 on my machine

# cached
print(timeit(stmt='get_ext("text")', globals={'get_ext': get_ext_cached}))
# 0.11434909792297276

Though for this particular case it's likely overkill and you can just call get on the dictionary directly (cache just builds its own dictionary and does exactly that) you can use this in future for any pure functions which are effectively a computed lookup.尽管对于这种特殊情况,它可能有点矫枉过正,您可以直接在字典上调用 get (缓存只是构建自己的字典并做到这一点),您将来可以将其用于任何有效的计算查找的纯函数。

d = {'text': ['txt', 'doc'],
    'audio': ['mp3', 'wav'],
    'video': ['mp4', 'mkv']}

# 0.05016115184298542
print(timeit(stmt="d['text']",
             globals={'d':d,'c':c}))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM