Як я можу виконувати функції псевдоніму в 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
Як я цього раніше не бачив?
Rainbolt

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)

Звичайно, це стосується лише одного конкретного випадку. Однак кодовий гольф - це пошук тих особливих випадків, які можуть врятувати вас на байтах.

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

Вам замість цього потрібно думати: "Я можу зробити це перетворення ефективно (по ходу) за допомогою str.replace. Чи можу я змістити внутрішнє представлення свого рішення, щоб скористатися цим?


Мені подобається ця відповідь, тому що вона описує хороші звички при гольфі і, безумовно, вирішує конкретний представлений приклад. Я прийняв ще одну відповідь, оскільки це стосується більш загального випадку.
Rainbolt

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)(інакше ми отримуємо якусь ключову помилку)? І навіщо це 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.