简体   繁体   English

将对象方法作为对象参数值传递

[英]Passing object method as the object argument value

I made a BetterMarker class that inherits from folium.Marker which is a geographic point object that can be added to a folium.Map object which produces a Leaflet HTML map.我创建了一个从folium.Marker继承的BetterMarker类,它是一个地理点对象,可以添加到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"

I can now initialize BetterMarker and add its instance to a folium.Map object:我现在可以初始化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

The code above works just fine producing the following map:上面的代码可以很好地生成以下地图:

在此处输入图片说明

However, instead of using the string Hi there in bm = BetterMarker(30, 40, popup = "Hi there") I want to use bm.north_or_south() :但是,不是在bm = BetterMarker(30, 40, popup = "Hi there")中使用字符串Hi there我想使用bm.north_or_south()

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

Of course, the above wouldn't work.当然,上面的方法是行不通的。 The code below would work, but it means initializing the class two times:下面的代码可以工作,但这意味着初始化类两次:

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

What's a sane way to do this?这样做的明智方法是什么? What did I do wrong?我做错了什么?

updated according to comment根据评论更新

My first attempt didn't fully understand the requirements.我的第一次尝试没有完全理解要求。 I think some of the other answers are on the right track.我认为其他一些答案是正确的。 Here's a way that works:这是一种有效的方法:

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"

As for calling, it's important to pass only the method and not to call it by including parentheses:至于调用,重要的是只传递方法而不是通过包含括号来调用它:

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

Notice I made a new keyword parameter called popup_method since popup meant the text.请注意,我创建了一个名为 popup_method 的新关键字参数,因为 popup 表示文本。 Also, I added longitude and kwargs to the popup method's signature so those methods have access to everything the caller passed.此外,我在 popup 方法的签名中添加了经度和 kwargs,以便这些方法可以访问调用者传递的所有内容。

Relating to comments in question.关于有问题的评论。 Something like so:像这样:

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

Edit编辑

As per the comment below, you could simply define the method(s) as @staticmethod :根据下面的评论,您可以简单地将方法定义为@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()

outputs:输出:

default
rand

[edit] Maybe just pass popup generating function as a keyword parameter? [编辑] 也许只是将弹出窗口生成函数作为关键字参数传递?

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")

you could try making north_or_south a static method您可以尝试使 north_or_south 成为静态方法

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

This makes it runnable from either an object or an object class, but the function itself doesn't know anything about the object it is being run from nor the class, so you can no longer have这使得它可以从对象或对象类运行,但函数本身不知道它正在运行的对象或类的任何信息,因此您不能再拥有

self.north_or_south()

as the function doesn't know anything about the object.因为函数对对象一无所知。 Instead we pass the latitude as an argument相反,我们将纬度作为参数传递

self.north_or_south(self.latitude)

and voila, it works.瞧,它起作用了。 The code gets a little longer but the function no longer needs an object from where to be run.代码变长了一点,但函数不再需要运行对象。 So in your problem you would simply have所以在你的问题中,你只会有

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM