[英]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
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.