Как мне псевдоним функции-члены в Python?


23

В Python можно сохранять байты, используя псевдонимы, которые используются многократно. Например:

r=range
a=r(100)
b=r(200)
c=r(300)

Тем не менее, когда функции являются функциями-членами вместе, я не знаю, как их псевдоним так, чтобы разрешить цепочки. Например:

s='Hello'

// Plain code
s=s.replace('H','J').replace('e','i').replace('l','m').replace('o','y')

// What I am trying to do
q=replace
s=s.q('H','J').q('e','i').q('l','m').q('o','y')

Очевидно, то, что я пытаюсь сделать, недопустимо. И это тоже

q=s.replace
s=q('H','J') // Replaces the 'H' in 'Hello'
s=q('e','i') // Replaces the 'e' in 'Hello'... and the J is gone.
s=q('l','m')
s=q('o','y')

Есть ли другой способ псевдонима функций-членов и связанных функций, который сохраняет символы?


Определите свой собственный класс, с его методом, qозначающим, что replaceозначает в классе, который вы используете.
Ypnypn

3
Я рад, что за это не проголосовали :)
TheDoctor

2
Я пока не отвечал на все ответы, но мы не достигли достаточно сильного консенсуса, чтобы призывать к отмене этого и подобных вопросов. См. Также: meta.codegolf.stackexchange.com/q/1555/3808
дверная ручка

3
Теперь, когда вышеупомянутая мета-дискуссия является полуофициальной (или, по крайней мере, большинство из нас согласны), я пошел дальше и удалил вики из этого поста.
Дверная ручка

1
Ваша последняя версия не работает. qсвязан с методом замены этого конкретного strэкземпляра. Кроме того, помните, что вы можете сделать замену одного символа с"Hello".replace(*"HJ")
gnibbler

Ответы:


28

Без проблем! Вы можете использовать псевдоним метода, но вы должны знать, как его использовать:

>>> r=str.replace
>>> a='hello'
>>> r(r(r(r(a,'h','j'),'e','i'),'l','m'),'o','y')
'jimmy'

Ключ заключается в том, что вы должны передать selfявно, потому что псевдоним является своего рода функцией, которая принимает дополнительный аргумент, который принимает self:

>>> type(r)
<type 'method_descriptor'>

3
Как я не видел это раньше?
Рейнболт

6

Определите свой собственный класс с более коротким именем метода.

Например, если вы используете метод, replace()принадлежащий Stringклассу, вы можете сделать так, чтобы в вашем собственном классе Sбыл вызван метод, qкоторый делает то же самое.

Вот одна реализация:

class m(str):
 def q(a,b,c):return m(a.replace(b,c))

Вот намного лучшая реализация:

class m(str):q=lambda a,b,c:m(a.replace(b,c))

Используйте это так:

s="Hello"
s=m(s).q('H','J').q('e','i').q('l','m').q('o','y')

5

Во всяком случае, это несколько символов короче

j=iter('HJeilmoy')
for i in j:s=s.replace(i,next(j))

еще короче для небольшого количества замен

for i in['HJ','ei','lm','oy']:s=s.replace(*i)

конечно, это только один конкретный случай. Тем не менее, Code Golf - это поиск особых случаев, которые могут сэкономить вам байты.

Можно написать функцию-обертку, которая обрабатывает общий случай, но код будет слишком большим, чтобы иметь место в большинстве задач, связанных с гольфом кода.

Вместо этого вам нужно подумать: «Я могу эффективно выполнить это преобразование (strokewise) с помощью str.replace. Могу ли я изменить внутреннее представление своего решения, чтобы воспользоваться этим? (Не тратя так много ударов, чтобы свести на нет преимущество)»


Мне очень нравится этот ответ, потому что он описывает хорошие привычки при игре в гольф и определенно решает конкретный представленный пример. Я принял другой ответ, потому что он применим к более общему случаю.
Рейнболт

4

Вы можете использовать reduceфункцию.

reduce(lambda s,(a,b):s.replace(a,b),[('H','J'),('e','i'),('l','m'),('o','y')],'Hello')

Если ваш ответ отличается от этого ответа (насколько используется метод, не обязательно записываются в точном же виде)?
Rainbolt

1
@Rusher Это другое. Например, количество вызовов жестко закодировано в связанном ответе, в то время как здесь оно задается только длиной второго аргумента (который может быть любым итератором).
Говард

1

Если вы делаете много замен, вы можете сделать это:

s=''.join({'H':'J','e':'i','l':'m','o':'y'}[a] for a in list(s))

Я надеялся на ответ, который не был определенным, чтобы заменить. Я просто использовал это в качестве примера.
Rainbolt

Это может заменить только 1 символ за раз, но он может вставлять замены из нескольких символов. И это не полностью игра в гольф (уберите место после [a])
Джастин

2
Не [a]нужно ли заменить на .get(a,a)(в противном случае мы получим что-то вроде Key Error)? И почему list(s)вместо s?
Джастин

1

Как насчет определения лямбда-функции?

r=lambda s,a,b:s.replace(a,b)

s=r(r(r(r(s,'H','J'),'e','i'),'l','m'),'o','y')

1
Нет необходимости: str.replace/ это / что лямбда! Смотри мой ответ.
MtnViewMark

1

Если ваши замены не должны быть связаны, вы можете использовать `str.translate '. Числа являются порядковыми номерами ASCII. Для использования этого способа требуется Python 3:

print("Hello".translate({72:74,101:105,108:109,111:121}))

Попробуйте онлайн

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.