我正在尝试在我正在使用的Python程序中使用一点继承。我有一个基类User,它实现了用户的所有功能。我添加了一个未经批准的用户的概念,就像用户一样,添加了一个方法。
User类有一些返回User对象的方法。当我进行子类化时,这将不起作用,因为我最终会让一个UnapprovedUser返回一个User,阻止我调用这个方法,等等。
class User(object):
base_dn = 'ou=Users,dc=example,dc=org'
@classmethod
def get(cls, uid):
ldap_data = LdapUtil.get(uid + ',' + self.base_dn)
return User._from_ldap(ldap_data)
class UnapprovedUser(User):
base_dn = 'ou=UnapprovedUsers,dc=example,dc=org'
def approve(self):
new_dn = '' # the new DN
LdapUtil.move(self.dn, new_dn)
两个类的get()
和_from_ldap()
方法相同,但UnapprovedUser中的get()
方法需要返回UnapprovedUser对象,而不是用户。
如何将我从User.get()
获得的用户实例之一投射到未经批准的用户?
我想做类似的事情:
class UnapprovedUser(User):
# continued from before
@classmethod
def get(cls, uid):
user = super(UnapprovedUser, cls).get(uid)
return (UnapprovedUser) user # invalid syntax
这样我就可以从父级中包装方法,只需将返回的值转换为正确的类。然后,这样做会导致父母使用他们的self.base_dn
值,这会破坏一切。
答案 0 :(得分:9)
我认为你真的想在调用UnapprovedUser
时创建User
而不是UnapprovedUser.get()
,而不是“投射”。要做到这一点:
更改User.get
以实际使用传入的cls
参数:
@classmethod
def get(cls, uid):
ldap_data = LdapUtil.get(uid + ',' + self.base_dn)
return cls._from_ldap(ldap_data)
您需要在_from_ldap
中执行类似的操作。你没有列出_from_ldap
的代码,但我认为在某些时候它会做类似的事情:
result = User(... blah ...)
您想将其替换为:
result = cls(... blah ...)
请记住:在Python中,类对象是一个可调用的,用于构造该类的实例。因此,您可以使用classmethod的cls
参数来构造用于调用classmethod的类的实例。
答案 1 :(得分:1)
Python是一种动态类型语言,因此不存在“强制转换”的概念。如果对象已经是UnapprovedUser
,那么您可以调用该类中存在的所有方法,而无需进行强制转换。
答案 2 :(得分:1)
在类方法中,类在cls参数中传入。因此,而不是User.something做cls.something。完成!
那就是说,我不确定我会用两种类型的用户来做这件事。我不是100%肯定你在这里说“批准”是什么意思,我觉得我是两件事之一。
这可能意味着用户尚未真正登录。在这种情况下,我有一个特殊的匿名用户实例,用于未登录的用户。由于您在批准时移动DN,因此这似乎更像是您正在做的事情。
这可能意味着用户尚未被批准为正式会员或其他内容。这只是权限处理的一个特例,您可能最终希望以后拥有更多权限。我会添加对提供用户角色的支持,并使“已批准”成为一个角色。
如果您的意思是批准的其他内容,请随意忽略这一点。 : - )
答案 3 :(得分:1)
super(UnapprovedUser,self)错了它应该是super(UnapprovedUser,cls),因为在类方法中你没有自己的可用
我将重申你的问题,在基类中你正在创建用户,不知何故你想要返回派生类,例如
class User(object):
@classmethod
def get(cls, uid):
return User()
class UnapprovedUser(User):
@classmethod
def get(cls, uid):
user = super(UnapprovedUser, cls).get(uid)
return user # invalid syntax
print UnapprovedUser.get("XXX")
它打印User对象而不是UnapprovedUser对象 在这里你希望UnapprovedUser.get返回UnapprovedUser,因为你可以创建一个工厂函数,它将返回适当的用户,而不是用ldap填充它
class User(object):
@classmethod
def get(cls, uid):
return cls.getMe()
@classmethod
def getMe(cls):
return cls()
class UnapprovedUser(User):
@classmethod
def get(cls, uid):
user = super(UnapprovedUser, cls).get(uid)
return user
print UnapprovedUser.get("XXX")
打印UnapprovedUser对象
答案 4 :(得分:0)
class A:
def __init__(self, variable):
self.a = 10
self.a_variable = variable
def do_something(self):
print("do something A")
class B(A):
def __init__(self, variable=None):
super().__init__(variable)
self.b = 15
@classmethod
def from_A(cls, a: A):
# Create new b_obj
b_obj = cls()
# Copy all values of A to B
# It does not have any problem since they have common template
for key, value in a.__dict__.items():
b_obj.__dict__[key] = value
return b_obj
if __name__ == "__main__":
a = A(variable="something")
b = B.from_A(a=a)
print(a.__dict__)
print(b.__dict__)
b.do_something()
print(type(b))
结果:
{'a': 10, 'a_variable': 'something'}
{'a': 10, 'a_variable': 'something', 'b': 15}
do something A
<class '__main__.B'>