我编写了以下python类。现在,我在每个函数中都重复if settings.MIXPANEL_ID:
,我想知道是否有更好的方法编写此类?
class MixpanelClass:
def __init__(self):
if settings.MIXPANEL_ID:
mp = Mixpanel(settings.MIXPANEL_ID)
def mp_track_event(user_id, event, property=None):
if settings.MIXPANEL_ID:
mp.track(user_id, event, property)
def mp_people_set(user_id, property):
if settings.MIXPANEL_ID:
mp.people_set(user_id, property)
def mp_people_increment(user_id, property):
if settings.MIXPANEL_ID:
mp.people_increment(user_id, property)
def mp_people_track_charge(user_id, revenue, property):
if settings.MIXPANEL_ID:
mp.people_track_charge(user_id, revenue, property)
def mp_get_distinct_id(request):
if settings.MIXPANEL_ID:
mp_cookie_name = 'mp_' + settings.MIXPANEL_ID + '_mixpanel'
mp_cookie = request.COOKIES.get(mp_cookie_name, None)
if mp_cookie:
unquoted = unquote(mp_cookie)
dictionary = literal_eval(unquoted)
return dictionary.get('distinct_id')
答案 0 :(得分:1)
您可以使用类装饰器(如果需要,可以装饰单个方法):
class enable_if:
def __init__(self, condition):
self.condition = condition
def __call__(self, obj):
if isinstance(obj, type):
return self.decorate_class(obj)
return self.decorate_callable(obj)
def decorate_class(self, cls):
for name in dir(cls):
attr = getattr(cls, name)
if callable(attr) and (name == '__init__' or not name.startswith('__') and not name.endswith('__')):
setattr(cls, name, self.decorate_callable(attr))
return cls
def decorate_callable(self, func):
def wrapper(obj, *args, **kwargs):
if self.condition:
return func(obj, *args, **kwargs)
return wrapper
这样可以:
@enable_if(settings.MIXPANEL_ID)
class MixpanelClass:
def __init__(self):
mp = Mixpanel(settings.MIXPANEL_ID)
def mp_track_event(user_id, event, property=None):
mp.track(user_id, event, property)
def mp_people_set(user_id, property):
mp.people_set(user_id, property)
def mp_people_increment(user_id, property):
mp.people_increment(user_id, property)
def mp_people_track_charge(user_id, revenue, property):
mp.people_track_charge(user_id, revenue, property)
def mp_get_distinct_id(request):
mp_cookie_name = 'mp_' + settings.MIXPANEL_ID + '_mixpanel'
mp_cookie = request.COOKIES.get(mp_cookie_name, None)
if mp_cookie:
unquoted = unquote(mp_cookie)
dictionary = literal_eval(unquoted)
return dictionary.get('distinct_id')
如果__init__
为MixpanelClass
,则settings.MIXPANEL_ID
类的每个用户方法和False
方法将被禁用。
答案 1 :(得分:0)
我要提个建议,但是,我认为这仍然需要原始海报中的更多信息。
您可以在要调用的方法上实现一个泛型函数。您必须将函数/方法作为参数传递给该函数
例如
def act_if_MIXPANEL_ID(self, method, *args, **kwargs):
"""Calls the method METHOD with the given args and kwargs"""
if settings.MIXPANEL_ID:
method(*args, **kwargs)
然后您可以使用以下代码调用此方法:
class MixpanelClass(object):
# here goes the rest of your code
def mp_track_event(self, user_id, event, property=None):
self.act_if_MIXPANEL_ID(self.mp.track, user_id, event, property)
def act_if_MIXPANEL_ID(self, method, *args, **kwargs):
"""Calls the method METHOD with the given args and kwargs"""
if settings.MIXPANEL_ID:
method(*args, **kwargs)
PS:我可以自由地将静态变量转换为标准方法。
或者,您可以定义一个装饰器并使用它来注释您的方法。在对该方法的任何调用之前,装饰器将被调用。 它将调用做检查(在本例中打印其他内容)
有关装饰器的快速介绍,请参见此处:Intro
# This is the decorator
def check_settings(func):
def wrapper(*args, **kwargs):
if settings.MIXPANEL_ID:
func(*args, **kwargs)
else:
print("Check for settings.MIXPANEL_ID failed.")
return wrapper
class MixpanelClass:
def __init__(self):
if settings.MIXPANEL_ID:
mp = Mixpanel(settings.MIXPANEL_ID)
@check_settings
def mp_track_event(user_id, event, property=None):
mp.track(user_id, event, property)
@check_settings
def mp_people_set(user_id, property):
mp.people_set(user_id, property)
@check_settings
def mp_people_increment(user_id, property):
mp.people_increment(user_id, property)
答案 2 :(得分:0)
如果未设置settings.MIXPANEL_ID
,则似乎没有任何意义拥有MixpanelClass
的实例。这表明像这样的类定义
class MixpanelClass:
def __init__(self, mp_id):
self.mp_id = mp_id
self.mp = Mixpanel(mp_id)
def mp_track_event(self, user_id, event, property=None):
self.mp.track(user_id, event, property)
def mp_people_set(self, user_id, property):
self.mp.people_set(user_id, property)
def mp_people_increment(self, user_id, property):
self.mp.people_increment(user_id, property)
def mp_people_track_charge(self, user_id, revenue, property):
self.mp.people_track_charge(user_id, revenue, property)
def mp_get_distinct_id(self, request):
mp_cookie_name = 'mp_' + self.mp_id + '_mixpanel'
mp_cookie = request.COOKIES.get(mp_cookie_name, None)
if mp_cookie:
unquoted = unquote(mp_cookie)
dictionary = literal_eval(unquoted)
return dictionary.get('distinct_id')
现在,仅当您实际上具有 ID时,才实例化MixpanelClass
:
if settings.MIXPANEL_ID:
m = MixpanelClass(settings.MIXPANEL_ID)