现在跟随我的一系列"python新手问题"并基于另一个问题.
转到http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables并向下滚动到"默认参数值".在那里你可以找到以下内容:
def bad_append(new_item, a_list=[]):
a_list.append(new_item)
return a_list
def good_append(new_item, a_list=None):
if a_list is None:
a_list = []
a_list.append(new_item)
return a_list
Run Code Online (Sandbox Code Playgroud)
在python.org上甚至还有一个"重要的警告",这个例子非常相同,并不是说它"更好".
所以,这里的问题是:为什么在一个已知问题上的"好"语法比在一个促进"优雅语法"和"易于使用"的编程语言中那样丑陋?
编辑:
我不是在问为什么或如何发生(感谢Mark的链接).
我问为什么没有更简单的替代内置语言.
我认为更好的方法可能是在def自身中做一些事情,其中name参数将附加到def可变对象中的"本地"或"新" .就像是:
def better_append(new_item, a_list=immutable([])):
a_list.append(new_item)
return a_list
Run Code Online (Sandbox Code Playgroud)
我相信有人可以提供更好的语法,但我也猜测必须有一个非常好的解释为什么没有这样做.
我想在python中创建一个redis缓存,就像任何一个自尊的科学家一样,我做了一个基准测试来测试性能.
有趣的是,redis并没有那么好.要么Python正在做一些神奇的事情(存储文件),要么我的版本的redis非常慢.
我不知道这是因为我的代码的结构方式,还是什么,但是我期待redis比它更好.
要创建redis缓存,我将二进制数据(在本例中为HTML页面)设置为从文件名派生的密钥,其有效期为5分钟.
在所有情况下,使用f.read()完成文件处理(这比f.readlines()快约3倍,我需要二进制blob).
在我的比较中是否存在我缺少的东西,或者Redis真的与磁盘不匹配?Python是否在某处缓存文件,并且每次都重新访问它?为什么这比访问redis要快得多?
我在64位Ubuntu系统上使用redis 2.8,python 2.7和redis-py.
我不认为Python正在做任何特别神奇的事情,因为我创建了一个将文件数据存储在python对象中并永久产生它的函数.
我有四个函数调用我分组:
读取文件X次
调用一个函数来查看redis对象是否仍在内存中,加载它或缓存新文件(单个和多个redis实例).
一个创建生成器的函数,该生成器从redis数据库生成结果(具有redis的单个和多个实例).
最后,将文件存储在内存中并永久生成.
import redis
import time
def load_file(fp, fpKey, r, expiry):
with open(fp, "rb") as f:
data = f.read()
p = r.pipeline()
p.set(fpKey, data)
p.expire(fpKey, expiry)
p.execute()
return data
def cache_or_get_gen(fp, expiry=300, r=redis.Redis(db=5)):
fpKey = "cached:"+fp
while True:
yield load_file(fp, fpKey, r, expiry)
t = time.time()
while time.time() - t - expiry < 0:
yield r.get(fpKey)
def cache_or_get(fp, expiry=300, r=redis.Redis(db=5)):
fpKey = "cached:"+fp
if r.exists(fpKey):
return r.get(fpKey) …Run Code Online (Sandbox Code Playgroud) 我试图在for循环中创建tkinter中的按钮.并且每个循环都将i count值作为参数传递给命令值.因此,当从命令值调用函数时,我可以判断按下了哪个按钮并相应地执行操作.问题是,假设len为3,它将创建3个按钮,标题为"Game 1"到"Game 3",但是当按下任何按钮时,打印值总是2,即最后一次迭代.因此看起来按钮是作为单独的实体制作的,但命令参数中的i值似乎完全相同.这是代码:
def createGameURLs(self):
self.button = []
for i in range(3):
self.button.append(Button(self, text='Game '+str(i+1),command=lambda:self.open_this(i)))
self.button[i].grid(column=4, row=i+1, sticky=W)
def open_this(self, myNum):
print(myNum)
Run Code Online (Sandbox Code Playgroud)
有没有办法在每次迭代时获得当前的i值以坚持使用该特定按钮?
当您使用数组参数在Python中定义函数时,该参数的范围是什么?
这个例子来自Python教程:
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
print f(3)
Run Code Online (Sandbox Code Playgroud)
打印:
[1]
[1, 2]
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
我不太确定我是否理解这里发生的事情.这是否意味着数组的范围超出了函数的范围?为什么数组会记住从调用到调用的值?来自其他语言,只有当变量是静态的时候我才会期望这种行为.否则它似乎应该每次重置.实际上,当我尝试以下内容时:
def f(a):
L = []
L.append(a)
return L
Run Code Online (Sandbox Code Playgroud)
我得到了我期望的行为(每次调用都重置了数组).
所以在我看来,我只需要def f(a, L=[]):解释这一行- L变量的范围是什么?
我有两个函数返回一个函数列表.函数接受一个数字x并添加i到它.i是一个从0-9增加的整数.
def test_without_closure():
return [lambda x: x+i for i in range(10)]
def test_with_yield():
for i in range(10):
yield lambda x: x+i
Run Code Online (Sandbox Code Playgroud)
我希望test_without_closure返回一个包含10个函数的列表,每个函数都添加9到x自i的值以来9.
print sum(t(1) for t in test_without_closure()) # prints 100
Run Code Online (Sandbox Code Playgroud)
我希望它test_with_yield也会有相同的行为,但它正确地创建了10个函数.
print sum(t(1) for t in test_with_yield()) # print 55
Run Code Online (Sandbox Code Playgroud)
我的问题是,在Python中屈服形成一个闭包吗?
我正在学习Python,我正在处理Mutable Default Argument问题.
# BAD: if `a_list` is not passed in, the default will wrongly retain its contents between successive function calls
def bad_append(new_item, a_list=[]):
a_list.append(new_item)
return a_list
# GOOD: if `a_list` is not passed in, the default will always correctly be []
def good_append(new_item, a_list=None):
if a_list is None:
a_list = []
a_list.append(new_item)
return a_list
Run Code Online (Sandbox Code Playgroud)
我知道a_list只有在def第一次遇到语句时才初始化,这就是为什么后续调用bad_append使用相同的列表对象的原因.
我不明白的是为什么good_append有所不同.它看起来像a_list会仍然只初始化一次; 因此,该if语句仅在第一次调用函数时才为真,这意味着a_list只会[]在第一次调用时重置,这意味着它仍然会累积所有过去的new_item …
以Python函数的简单情况为例,该函数计算数学函数:
def func(x, a, b, c):
"""Return the value of the quadratic function, ax^2 + bx + c."""
return a*x**2 + b*x + c
Run Code Online (Sandbox Code Playgroud)
假设我想以函数属性的形式"附加"一些其他信息.例如,LaTeX表示.我知道,由于PEP232,我可以在函数定义之外执行此操作:
def func(x, a, b, c):
return a*x**2 + b*x + c
func.latex = r'$ax^2 + bx + c$'
Run Code Online (Sandbox Code Playgroud)
但我想在函数定义中做到这一点.如果我写
def func(x, a, b, c):
func.latex = r'$ax^2 + bx + c$'
return a*x**2 + b*x + c
Run Code Online (Sandbox Code Playgroud)
这当然有效,但只有在我func第一次调用之后(因为Python在执行函数时是"懒惰的"(?))
我是编写可调用类的唯一选择吗?
class MyFunction:
def __init__(self, func, latex):
self.func = …Run Code Online (Sandbox Code Playgroud) 在程序结束时,我希望将类的所有实例中的特定变量加载到字典中.
例如:
class Foo():
__init__(self):
x = {}
foo1 = Foo()
foo2 = Foo()
foo...etc.
Run Code Online (Sandbox Code Playgroud)
假设实例的数量会有所不同,我希望每个Foo()实例的x dict都加载到一个新的dict中.我该怎么办?
我在SO中看到的例子假设一个已经有实例列表.
我有不错的编程水平,并从这里的社区中获得了很多价值。然而,我从来没有在编程方面进行过太多的学术教学,也没有与真正有经验的程序员一起工作。因此,我有时会为“最佳实践”而苦恼。
对于这个问题,我找不到更好的地方,尽管可能有讨厌这些问题的喷子,我还是发布了这个。如果这让你感到不安,很抱歉。我只是想学习,而不是惹你生气。
题:
当我创建一个新类时,我是否应该在init 中设置所有实例属性,即使它们是 None 并且实际上后来在类方法中分配了值?
MyClass 的属性结果见下例:
class MyClass:
def __init__(self,df):
self.df = df
self.results = None
def results(df_results):
#Imagine some calculations here or something
self.results = df_results
Run Code Online (Sandbox Code Playgroud)
我在其他项目中发现,当类属性只出现在类方法中时,它们可能会被埋没,而且还有很多事情要做。
那么对于经验丰富的专业程序员来说,什么是标准做法呢?为了可读性,您会在init 中定义所有实例属性吗?
如果有人有任何关于我可以在哪里找到这些原则的材料的链接,那么请将它们放在答案中,我们将不胜感激。我知道 PEP-8 并且已经在上面搜索了我的问题好几次,但找不到任何涉及此问题的人。
谢谢
安迪
我创建了这样的Enum对象:
class Gender(Enum):
FEMALE = 'female'
MALE = 'male'
RANDOM = random.choice([FEMALE, MALE])
Run Code Online (Sandbox Code Playgroud)
我想每次都获得真正的随机值,但它不起作用:
>>> class Gender(Enum):
... MALE = 'male'
... FEMALE = 'female'
... RANDOM = choice([MALE, FEMALE])
...
>>> Gender.RANDOM
<Gender.MALE: 'male'>
>>> Gender.RANDOM
<Gender.MALE: 'male'>
>>> Gender.RANDOM
<Gender.MALE: 'male'>
>>> Gender.RANDOM
<Gender.MALE: 'male'>
Run Code Online (Sandbox Code Playgroud)
我也试过使用lambda,但看起来不太好,虽然它有效:
Gender.RANDOM()
Run Code Online (Sandbox Code Playgroud)
是否有其他方法可以每次获取随机值,而不使用lambda表达式?
我们使用这个枚举对象作为某个方法的参数的默认值,这就是为什么它应该是属性而不是函数,因为当我们使用Gender.FEMALE它时它不是一个函数,它是一个属性,也Gender.RANDOM应该是一个属性:
def full_name(gender=Gender.FEMALE):
...
def full_name(gender=Gender.RANDOM):
...
Run Code Online (Sandbox Code Playgroud) python ×10
class ×2
function ×2
mutable ×2
arguments ×1
button ×1
caching ×1
closures ×1
dictionary ×1
enums ×1
generator ×1
instance ×1
instances ×1
lambda ×1
names ×1
parameters ×1
performance ×1
python-3.x ×1
python-attrs ×1
random ×1
redis ×1
scope ×1
self ×1
tkinter ×1
yield ×1