让我们看一下 numpy 数组的一些非常简单的行为:
import numpy as np
arr = np.array([1,2,3,4,5])
max_value = arr.max() # returns 5
Run Code Online (Sandbox Code Playgroud)
现在我创建一个继承自的类np.ndarray:
class CustomArray(np.ndarray):
def __new__(cls, *args, **kwargs):
obj = np.array(*args, **kwargs).view(cls)
return obj
new_arr = CustomArray([1,2,3,4,5])
Run Code Online (Sandbox Code Playgroud)
我实际上并没有改变任何行为 - 我只是对对象的类进行了名义上的更改。
但是:
new_max_value = new_arr.max() # returns CustomArray(5)
Run Code Online (Sandbox Code Playgroud)
返回值是一个CustomArray实例?为什么?arr.max()没有返回np.ndarray实例,只是一个普通的 numpy 整数。
同样,为什么 和 都arr == new_arr返回new_arr == arr实例CustomArray?前者不应该调用arr.__eq__(new_arr),后者应该返回一个np.ndarray实例吗?
编辑:
__new__请注意,为了简单的构造函数,我重写了该方法。例如,相当于np.array([1,2,3,4,5])可以是CustomArray([1,2,3,4,5]),而如果我直接继承自,np.ndarray我就必须做类似的事情new_arr …
我正在尝试创建一个可滚动的Python Tkinter小部件,它可以包含其他小部件.下面的虚拟代码(主要取决于这个SO问题的答案,然后根据我的风格进行调整)似乎几乎完全符合我的要求:
import Tkinter as tk
class ScrollFrame(tk.Frame):
def __init__(self, root, *args, **kwargs):
# Start up self
tk.Frame.__init__(self, root, *args, **kwargs)
# Put a canvas in the frame (self), along with scroll bars
self.canvas = tk.Canvas(self)
self.horizontal_scrollbar = tk.Scrollbar(
self, orient="horizontal", command=self.canvas.xview
)
self.vertical_scrollbar = tk.Scrollbar(
self, orient="vertical", command=self.canvas.yview
)
self.canvas.configure(
yscrollcommand=self.vertical_scrollbar.set,
xscrollcommand=self.horizontal_scrollbar.set
)
# Put a frame in the canvas, to hold all the widgets
self.inner_frame = tk.Frame(self.canvas)
# Pack the scroll bars and the canvas (in …Run Code Online (Sandbox Code Playgroud) 我有一个非常大的数组,由0到N之间的整数组成,其中每个值至少出现一次.
我想知道,对于每个值k,我的数组中数组的值等于k的所有索引.
例如:
arr = np.array([0,1,2,3,2,1,0])
desired_output = {
0: np.array([0,6]),
1: np.array([1,5]),
2: np.array([2,4]),
3: np.array([3]),
}
Run Code Online (Sandbox Code Playgroud)
现在我正在完成这个循环range(N+1),并调用np.whereN次.
indices = {}
for value in range(max(arr)+1):
indices[value] = np.where(arr == value)[0]
Run Code Online (Sandbox Code Playgroud)
这个循环是我代码中最慢的部分.(arr==value评估和np.where通话都占用了大量的时间.)有没有更有效的方法来做到这一点?
我也试过玩,np.unique(arr, return_index=True)但只告诉我第一个索引,而不是所有索引.
我知道可以通过手动设置来更改轴标签。(例如:修改刻度标签文本)
然而,这显然只有在你知道你想要什么标签的情况下才有效,但对我来说情况并非如此。
这是我想要完成的示例:我有两个 numpy 数组:x包含 1 到 366 之间的数字(但不一定是全部),代表 2016 年的天数。“y”包含其他一些数字。我想制作“y”与“x”的散点图:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([27, 38, 100, 300])
y = np.array([0.5, 2.5, 1.0, 0.8])
plt.scatter(x, y)
Run Code Online (Sandbox Code Playgroud)
不出所料,这会生成一个刻度为 0、50、100、...、350 的图表。我想将这些刻度标签更改为各个日期。(例如,50 处的刻度线将被标记为“二月 19 日”之类的内容。)假设我有一个tick_to_date可以将数字 0 转换为日期字符串的函数,这样我就可以轻松手动更改图表中的所有刻度线。(如果您需要占位符功能tick_to_date = lambda x: ("day " + str(x)):)
ax = plt.gca()
ax.set_xticklabels([tick_to_date(tick.get_text()) for tick in ax.get_xticklabels()])
Run Code Online (Sandbox Code Playgroud)
然而,这只会执行一次。如果我现在放大或执行任何更改刻度的操作,新的刻度标签将不会是我想要的。
理想情况下,我不会手动设置标签,而是告诉轴始终使用我自己的tick_to_date函数转换刻度标签。或者,每次刻度线更改时都调用上面的代码行,但我不确定这是否会很好地工作。其中任何一个可能/可行/愉快可用吗?
TkinterListbox可以允许通过selectmode配置选择多个项目。但是,如果我现在以编程方式选择并激活一个条目,则将 Shift 键与向上或向下箭头键组合使用不会将选择范围扩展到当前项目上方/下方的项目,而只会激活该新项目,同时保留旧的选择。
例如,在以下 (Python 2.7) 代码中,我进行了子类化Listbox,以允许 Home 和 End 键分别选择列表中的第一项和最后一项:
import Tkinter as tk
class MyListbox(tk.Listbox):
def __init__(self, *args, **kwargs):
tk.Listbox.__init__(self, *args, **kwargs)
self.bind("<Home>", lambda *args: self.select(0))
self.bind("<End>", lambda *args: self.select("end"))
def select(self, index):
self.select_clear(0, "end")
self.selection_set(index)
self.see(index)
self.activate(index)
main = tk.Tk()
listbox = MyListbox(main, selectmode="extended")
for x in ["one", "two", "three", "four", "five"]:
listbox.insert("end", x)
listbox.pack()
tk.mainloop()
Run Code Online (Sandbox Code Playgroud)
这会产生一个窗口,其中有一个列表框。如果选择列表框并单击“结束”,则会选择最后一个元素(字符串“五”)。如果您现在按 Shift-Up,那么您会期望选择字符串“four”和“ Five”。相反,“四”在没有被选择的情况下被激活(如预期),并且“五”保持选中状态。
为什么除了“五”之外,没有选择“四”?我可以解决这个问题而不必重新绑定箭头键和朋友吗?
请注意,如果我通过单击某个项目或使用箭头键导航到该项目来选择该项目,则不会发生此行为。
如果更改numpy数组的视图,则原始数组也会更改。这是预期的行为。
arr = np.array([1,2,3])
mask = np.array([True, False, False])
arr[mask] = 0
arr
# Out: array([0, 2, 3])
Run Code Online (Sandbox Code Playgroud)
但是,如果我对这种视图进行更改,然后更改,则原始数组不会更改:
arr = np.array([1,2,3])
mask_1 = np.array([True, False, False])
mask_1_arr = arr[mask_1] # Becomes: array([1])
mask_2 = np.array([True])
mask_1_arr[mask_2] = 0
arr
# Out: array([1, 2, 3])
Run Code Online (Sandbox Code Playgroud)
对我而言,这意味着,当您查看某个视图时,您实际上会获得一份副本。它是否正确?为什么是这样?
如果我使用数字索引的numpy数组而不是布尔值的numpy数组,则会发生相同的行为。(例如arr[np.array([0])][np.array([0])] = 0,不会将第一个元素更改arr为0。)
据我所知,raise如果它是一个函数,而不是一个语句,它也会起作用.
在我看来,陈述的一个显着特征是他们的论点不被解释为"代码".例如import math,不要求你定义math,类似的函数需要一个字符串参数:import("math").
另一个是,如果一个参数被解释为代码,它不一定被评估.例如,assert testbool, myfunc()将只调用myfunc()如果testbool是True.
最后,我想使用语句而不是函数可以避免由于调用函数而产生的一些开销.
这些优点都不适用于raise:它的参数总是必须被定义,并且没有raise执行语句的情况,但是它的参数没有被计算.最后,我想象一下,与提出异常所涉及的所有其他簿记相比,调用函数的开销是微不足道的.
与此同时,raise作为一个声明的代价是不能使用该词raise作为变量的名称,这将看到很多用途,因为它是一个相当普遍的英语动词.(我可以筹集一个平台,将数字提高1,......)
我还想象有更少的语句会简化编译器.
那么为什么要raise发表声明呢?