Итак, я недавно возился с чем-то похожим на это, и я придумал следующее решение, которое использует способ ввода ввода, который отклоняет нежелательный файл, прежде чем он будет проверен любым логическим способом.
read_single_keypress()
любезность https://stackoverflow.com/a/6599441/4532996
def read_single_keypress() -> str:
"""Waits for a single keypress on stdin.
-- from :: https://stackoverflow.com/a/6599441/4532996
"""
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# save old state
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# make raw - the way to do this comes from the termios(3) man page.
attrs = list(attrs_save) # copy the stored version to update
# iflag
attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
| termios.ISTRIP | termios.INLCR | termios. IGNCR
| termios.ICRNL | termios.IXON )
# oflag
attrs[1] &= ~termios.OPOST
# cflag
attrs[2] &= ~(termios.CSIZE | termios. PARENB)
attrs[2] |= termios.CS8
# lflag
attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
| termios.ISIG | termios.IEXTEN)
termios.tcsetattr(fd, termios.TCSANOW, attrs)
# turn off non-blocking
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# read a single keystroke
try:
ret = sys.stdin.read(1) # returns a single character
except KeyboardInterrupt:
ret = 0
finally:
# restore old state
termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return ret
def until_not_multi(chars) -> str:
"""read stdin until !(chars)"""
import sys
chars = list(chars)
y = ""
sys.stdout.flush()
while True:
i = read_single_keypress()
_ = sys.stdout.write(i)
sys.stdout.flush()
if i not in chars:
break
y += i
return y
def _can_you_vote() -> str:
"""a practical example:
test if a user can vote based purely on keypresses"""
print("can you vote? age : ", end="")
x = int("0" + until_not_multi("0123456789"))
if not x:
print("\nsorry, age can only consist of digits.")
return
print("your age is", x, "\nYou can vote!" if x >= 18 else "Sorry! you can't vote")
_can_you_vote()
Здесь вы можете найти полный модуль здесь .
Пример:
$ ./input_constrain.py
can you vote? age : a
sorry, age can only consist of digits.
$ ./input_constrain.py
can you vote? age : 23
your age is 23
You can vote!
$ _
Обратите внимание, что природа этой реализации заключается в том, что она закрывает stdin, как только считывается что-то, что не является цифрой. Я не попал в enter после a
, но мне нужно было после чисел.
Вы можете объединить это с функцией thismany()
в том же модуле, чтобы разрешить, скажем, три цифры.
Порядок детерминирован, но часть частных кишок поэтому может быть изменена в любое время, см. код здесь (элементы self.*
- это списки художников, которые были добавлены, следовательно [1]
Если вы хотите явно контролировать порядок элементов в вашей легенде, тогда соберите список обработчиков и меток, как вы это делали в ваше редактирование.
Следующая функция ищет дескрипторы дескрипторов и меток и сортирует или частично сортирует их в соответствии с заданным списком (order
):
def reorderLegend(ax=None,order=None,unique=False):
"""
Returns tuple of handles, labels for axis ax, after reordering them to conform to the label order `order`, and if unique is True, after removing entries with duplicate labels.
"""
if ax is None: ax=plt.gca()
handles, labels = ax.get_legend_handles_labels()
# sort both labels and handles by labels
labels, handles = zip(*sorted(zip(labels, handles), key=lambda t: t[0]))
if order is not None: # Sort according to a given list (not necessarily complete)
keys=dict(zip(order,range(len(order))))
labels, handles = zip(*sorted(zip(labels, handles), key=lambda t,keys=keys: keys.get(t[0],np.inf)))
if unique: # Keep only the first of each handle
labels, handles= zip(*unique_everseen(zip(labels,handles), key = labels))
ax.legend(handles, labels)
return(handles, labels)
def unique_everseen(seq, key=None):
seen = set()
seen_add = seen.add
return [x for x,k in zip(seq,key) if not (k in seen or seen_add(k))]
Функция в обновленной форме находится в cpblUtilities.mathgraph
в http://github.com/cpbl
Цитаты: Кевин (эта страница) и Маркус Ярдерот ( Как удалить дубликаты из списка в сохраняя порядок? ).
Небольшое отклонение от некоторых других участников. Список order
должен иметь ту же длину, что и количество элементов легенды, и задает новый порядок вручную.
handles, labels = plt.gca().get_legend_handles_labels()
order = [0,2,1]
plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
Вот быстрый фрагмент для сортировки записей в легенде. Предполагается, что вы уже добавили элементы графика с меткой, например, как
ax.plot(..., label='label1')
ax.plot(..., label='label2')
, а затем основной бит:
handles, labels = ax.get_legend_handles_labels()
# sort both labels and handles by labels
labels, handles = zip(*sorted(zip(labels, handles), key=lambda t: t[0]))
ax.legend(handles, labels)
Это всего лишь простая адаптация из кода, указанного в http://matplotlib.org/users/legend_guide.html