Скажем, у меня есть простой класс связанного списка:
class LL:
def __init__(self):
self.next = None
self.previous = None
def next(self):
return self.next
def previous(self):
return self.previous
В этом случае я хочу вызвать предыдущий или следующий, в зависимости от того, что передается в функцию в другом классе, например:
class foo:
def __init__(self):
self.node = LL()
def move(direction):
self.node = self.node.direction
S.t. когда он звонит, он звонит self.node.next()
или self.node.previous()
.
Где move ("следующий") будет вызывать self.node.next()
.
Это не работает. И не
self.node = self.node.direction()
Как я могу сделать что-то подобное?
Я не уверен, как даже формально описать это - присвоение атрибута класса путем вызова метода альтернативного класса через параметр?
Почему вообще существуют ваши методы next
и previous
? Они не обеспечили бы никакой полезной функциональности, даже если бы они не были скрыты назначениями self.next = None
и self.previous = None
.
@ user2357112 В идеале это сделало бы программу, которую я создаю, немного более расширяемой в будущем. Сейчас я использую связанный список с 4 направлениями, но это был ясный и простой пример. @ juanpa.arrivillaga Я стараюсь избегать длинного списка операторов if
, чтобы в будущем я мог добавить больше модульности к тому, как все движется.
@Whatamia, вы также можете использовать getattr
. Но как долго это слишком долго? Как вы думаете, сколько из этих атрибутов необходимо поддерживать?
@ juanpa.arrivillaga Справедливая критика. Казалось бы, getattr действительно сделает то, что я хочу. Спасибо. Я также одобряю другой ответ, поскольку он также дает то же самое.
В вашем случае было бы лучше сделать это простым с помощью оператора if
.
def move(direction):
if direction == 'next':
self.node = self.node.next()
elif direction == 'previous':
self.node = self.node.previous()
else:
#handle the invalid input however you think is best
Однако следует переименовать поле или метод как для next
, так и для previous
. Я бы порекомендовал заменить next(self)
на getNext(self)
. В качестве альтернативы вы можете изменить self.next
на self._next
, чтобы указать, что поле не предназначено для прямого доступа.
Не забудьте вызвать методы с ()
.
@Idlehands в этом случае фактически потерпит неудачу, поскольку атрибут экземпляра и имена методов конфликтуют
@Idlehands Хороший улов. Методы бессмысленны, как показано, но очевидно, что OP хочет что-то делать.
@ juanpa.arrivillaga да, я тоже уловил оба ваших комментария. Я просто комментирую реализацию этого ответа.
Я бы посоветовал просто не использовать метод и использовать прямой доступ к атрибутам, поскольку это был бы питонический путь. Однозначно никогдаgetX
....
@ juanpa.arrivillaga Я профессионально занимаюсь программированием на Java. Я никогда не понимал, что сообщества Python не принимают это соглашение об именах. Есть ли какая-то конкретная причина, почему не getX
?
Потому что вам не следует писать геттеры и сеттеры на Python для простого доступа к атрибутам и их извлечения. Так что не используйте obj.getX
, просто используйте obj.x
. Не используйте obj.setX(val)
, используйте obj.x = val
. Если позже вы решите управлять доступом к атрибуту, вы можете использовать property
, но вы все равно можете использовать obj.x
и obj.x = val
. Свойства - это то, как Python выполняет инкапсуляцию. Прочтите это: python-course.eu/python3_properties.php
Как продемонстрировал @ user2357112, ваш класс LL
сам по себе имеет проблемы с теневым копированием. Вы, вероятно, захотите изменить его, возможно, на одно из следующих:
class LL:
def __init__(self):
self._next = None
self._previous = None
# assign a different name
def next(self):
... do something like move the node to next
... maybe change self._next on the way...
return self._next
# Or make use of property decorator
@property
def previous(self):
... do something like move the node to previous
return self._previous
@previous.setter
def previous(self, value):
... do something to change self._previous
Почему-то я все еще не думаю, что это то, что вам нужно, но чтобы ответить на дух вашего вопроса, вы можете использовать dict
как оператор switch в своем классе foo()
следующим образом:
class foo:
def __init__(self):
self.node = LL()
def move(direction):
_moves = {
'next': self.node.next,
'previous': self.node.previous,
'nowhere': self.node.nowhere
}
# if you're invoking a method
_moves.get(direction)()
# if you're just referencing an attribute
_moves.get(direction)
Концептуально я думаю, что более важно подумать о том, чего вы пытаетесь достичь с помощью LL
и foo
, прежде чем продолжить.
ну а как насчет
if direction == "next": node.next() elif direction == 'previous' ...
и тд?