2015-05-29 77 views
3

方法1(全局变量):为函数的Python最佳实践

id_constant = 1000 
id_cnt = 1 
def give_id(): 
    global id_cnt 
    id_cnt += 1 
    return id_constant * id_cnt 
id = give_id() 

方法2(FUC变种而不是全局变量):

id_cnt = 1 
def give_id(): 
    id_constant = 1000 
    global id_cnt 
    id_cnt += 1 
    return id_constant * id_cnt 
id = give_id() 

方法3(通过在全局变量):

id_cnt = 1 
id_constant = 1000 
def give_id(constant, cnt): 
    return constant * cnt 
global id_cnt 
id_cnt +=1 
id = give_id(id_constant, id_cnt) 

即时通讯不确定是否有任何一般的经验法则,但是被广泛接受的函数来访问一个函数内的全局变量重刑?或者如果变量只用于一个函数,那么它应该是一个函数变量的一部分吗?

+2

有时是必要的,但总的来说,在所有的语言,访问'global'变量是不好的做法 – Scironic

+1

一般较少的全局变量意味着更好的代码,所以尝试使用参数并返回值而不是全局变量。什么来问你的问题,上下文将有助于为你选择最好的方法。你在用什么ID? –

+0

不要忘记你可以在函数参数中使用默认值,例如:'def foo(bar = 4):\ print bar',如果调用为'foo()',将会打印'4'。通常这对于很少更改的配置变量来说更好,因为它避免了全局变量(实际上是模块级别的变量),并且保持常量接近代码中的使用。 – thirtythreeforty

回答

4

该方法通常取决于情况。

你似乎需要唯一的ID,为什么不使用发电机

def create_id_generator(): 
    """Returns an id generator.""" 
    i = 0 
    while True: 
     yield i 
     i += 1 

使用的next()功能:如果你想要的ID是的1000倍数

>>> ID_GENERATOR = create_id_generator() # Global variable 
>>> my_id = next(ID_GENERATOR) 
>>> my_id2 = next(ID_GENERATOR) 
>>> my_id3 = next(ID_GENERATOR) 
>>> print(my_id, my_id2, my_id3, next(ID_GENERATOR)) 
0 1 2 3 

,您可以通过参数将常数传递给发电机:

def create_id_generator(multiplier=1000): 
    """Returns an id generator.""" 
    i = 0 
    while True: 
     yield i * multiplier 
     i += 1 

你甚至可以添加一个初始值,如果你不想从指数0开始:

def create_id_generator(multiplier=1000, start_index=0): 
    """Returns an id generator.""" 
    while True: 
     yield start_index * multiplier 
     start_index += 1 
2

通过Python的禅(即import this

Namespaces are one honking great idea -- let's do more of those! 

一般来说,如果你不需要把东西在全局命名空间,最好是将其封装在函数的局部命名空间,所以我会认为选项2会更“pythonic”,除非id_constant将被多个函数使用。

您也可以尝试以下使用关键字参数有一个默认值:

id_cnt = 1 
def give_id(id_constant=1000): 
    global id_cnt 
    id_cnt += 1 
    return id_constant * id_cnt 
id = give_id() 

然后,如果你曾经需要id_constant是不同的东西,你可以调用函数为ID = give_id(id_constant = 500 )。

+1

在当前版本中,函数参数被忽略。 – kratenko

+0

哎呀!谢谢你的收获 –

3

如果id_constant实际上不变,我会做:

ID_CONSTANT = 1000 

def give_id(id_count): 
    return ID_CONSTANT * id_count 

id_count = 1 

id = give_id(id_count) 

但它看起来像你也有一些国家(id_count),需要与发行id保持最新,建议发电机功能:

def give_id(id_count): 
    while True: 
     yield ID_CONSTANT * id_count 
     id_count += 1 

甚至类:

class IdCreator(object): 

    ID_CONSTANT = 1000 

    def __init__(self, start_count=1): 
     self.id_count = start_count 

    def give_id(self): 
     new_id = self.ID_CONSTANT * self.id_count 
     self.id_count += 1 
     return new_id 

你可以进一步和implement iteration去的类。

2

全局变量通常是您应该避免的。

如果你想拥有常数,对我们说,配置目的,我会采取更象一个模块的方法:

conf.py

MYCONST = 1000 

app.py

import conf 

print conf.MYCONST 

或采取面向对象方法,如:

class Test(object): 

    def __init__(self): 
     self._constant = 1000 

    def give_id(self, cnt): 
     return self._constant * cnt 
1

可能您需要生成器函数?

def give_id(id_constant): 
    delta = 0 
    while True: 
     delta += 1 
     yield id_constant + delta 

for i in range(100): 
    print(give_id(1000)) # prints numbers from 1001 to 1100 
1

的棘手的东西一点点:

def get_id_func(constant): 
    class c(object): 
     def __init__(self, constant): 
      self.constant = constant 
      self.id = 0 
     def func(self): 
      self.id += 1 
      return self.id * self.constant 
    o = c(constant) 
    return o.func 

# create function 
f = get_id_func(1000) 

# call and test it 
assert f() == 1000 
assert f() == 2000 
assert f() == 3000