Передача метода объекта в качестве значения аргумента объекта - PullRequest
4 голосов
/ 20 февраля 2020

Я создал класс BetterMarker, который наследуется от folium.Marker, который является географическим c точечным объектом, который можно добавить к объекту folium.Map, который создает карту Leaflet HTML.

import folium, datetime

class BetterMarker(folium.Marker):

    def __init__(self, latitude, longitude, **kwargs): 
        super().__init__([latitude, longitude], **kwargs)
        self.latitude = latitude

    def north_or_south(self):
        if self.latitude > 0:
            return "North"
        else:
            return "South"

Теперь я могу инициализировать BetterMarker и добавить его экземпляр к folium.Map объекту:

mymap = folium.Map() # Create Map object
bm = BetterMarker(30, 40, popup = "Hi there")
bm.add_to(mymap) # Add BetterMarker object to Map
mymap.save("mymap.html") # Save the map with the marker into HTML

Приведенный выше код прекрасно работает, создавая следующую карту:

enter image description here

Однако вместо использования строки Hi there в bm = BetterMarker(30, 40, popup = "Hi there") я хочу использовать bm.north_or_south():

bm = BetterMarker(30, 40, popup = bm.north_or_south())

Конечно, вышеприведенное т работа. Код ниже будет работать, но это означает, что класс нужно инициализировать два раза:

bm = BetterMarker(30, 40)
bm = BetterMarker(30, 40, popup = bm.north_or_south())

Что такое разумный способ сделать это? Что я сделал не так?

Ответы [ 4 ]

3 голосов
/ 29 февраля 2020

обновлено согласно комментарию

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

class BetterMarker(folium.Marker):

    def __init__(self, latitude, longitude, **kwargs):
        if kwargs['popup_method']:
            kwargs['popup'] = kwargs['popup_method'](latitude, longitude, **kwargs)
            del kwargs['popup_method']
        super().__init__([latitude, longitude], **kwargs)

    @staticmethod
    def quadrant(latitude, longitude, **kwargs):
        if latitude > 0 and longitude > 0:
            return "North East"
        elif latitude > 0 and longitude <= 0:
            return "North West"
        elif latitude <= 0 and longitude > 0:
            return "South East"
        else:
            return "South West"

Что касается вызова, важно передать только метод и не вызывать его, включая скобки:

bm = BetterMarker(-30, 40, popup_method=BetterMarker.quadrant)

Обратите внимание, что я создал новое ключевое слово параметр называется popup_method, поскольку popup означает текст. Кроме того, я добавил longitude и kwargs в сигнатуру метода popup, чтобы эти методы имели доступ ко всему, что передавал вызывающий.

0 голосов
/ 29 февраля 2020

вы можете попробовать сделать north_or_south статическим c методом

@staticmethod
def north_or_south(latitude):
    if latitude > 0:
        return "North"
    else:
        return "South"

Это делает его работоспособным из объекта или класса объекта, но сама функция ничего не знает об объекте, которым она является будучи запущенным из класса или класса, вы больше не можете иметь

self.north_or_south()

, так как функция ничего не знает об объекте. Вместо этого мы передаем широту в качестве аргумента

self.north_or_south(self.latitude)

и вуаля, это работает. Код становится немного длиннее, но функция больше не нуждается в объекте, откуда ее запускать. Таким образом, в вашей задаче у вас будет просто

bm = BetterMarker(30, 40, popup = BetterMarker.north_or_south(40))
0 голосов
/ 28 февраля 2020

[edit] Может быть, просто передать функцию генерации всплывающих окон в качестве параметра ключевого слова?

import folium, datetime

class CustomPopup:
       @staticmethod
       def north_or_south(latitude, longtitude, **kwargs):
        if latitude > 0:
            return "North"
        else:
            return "South" 

        ...other methods

class BetterMarker(folium.Marker):

    def __init__(self, latitude, longitude, **kwargs): 
        self.latitude = latitude
        if 'msg' in kwargs:
             kwargs['popup'] = kwargs['msg'](latitude, longtitude, **kwargs)
        super().__init__([latitude, longitude], **kwargs)


mymap = folium.Map() # Create Map object
bm = BetterMarker(30, 40, msg=CustomPopup.north_or_south)
bm.add_to(mymap) # Add BetterMarker object to Map
mymap.save("mymap.html")
0 голосов
/ 20 февраля 2020

Относительно комментариев в вопросе. Примерно так:

class Foo:
    def __init__(self, *args, **kwargs):
        self.alert = kwargs['alert']

    def print_alert(self):
        print(self.alert())

class Bar(Foo):
    def __init__(self, *args, **kwargs):
        if "alert" not in kwargs:
            kwargs['alert'] = self.custom_alert() # Notice here.

        super().__init__(*args, **kwargs)

    def custom_alert(self):
        return "Custom Alert"

Bar().print_alert() # >>> Custom Alert

Редактировать

Согласно комментарию ниже, вы можете просто определить метод (ы) как @staticmethod:

class Foo:
    def __init__(self, *args, **kwargs):
        self.alert = kwargs["alert"]

    def print_alert(self):
        print(self.alert()) # Notice we DO call the variable.


class Bar(Foo):
    def __init__(self, *args, **kwargs):
        if "alert" not in kwargs:
            kwargs["alert"] = self.default_alert

        super().__init__(*args, **kwargs)

    @staticmethod
    def default_alert():
        return "Custom Alert!"

    @staticmethod
    def random_alert():
        return "Random Alert!"


a = Bar()
a.print_alert()

b = Bar(alert=Bar.random_alert)  # Notice we do not CALL the method.
b.print_alert()

выходы:

default
rand
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...