How do you cast an instance to a derived class?

前端 未结 5 1885

I am trying to use a little inheritance in a Python program I am working on. I have a base class, User, which implements all of the functionality of a user. I am adding the co

相关标签:
5条回答
  • 2021-02-13 23:31

    In a class method, the class is passed in in the cls parameter. So instead of User.something do cls.something. Done!

    That said, I'm not sure I would do this with two types of user. I'm not 100% sure what you mean with "Approved" here, I it seems to me to be one of two things.

    1. It may mean the user isn't really logged in yet. In that case I'd have a special Anonymous User instance for not logged in users. Since you are moving the DN when approving, this seems more likely to be what you are doing.

    2. It may mean that the user hasn't been approved as a full member or something. This is just a special case of permission handling, and you are probably going to end up wanting to have more permissions later. I'd instead add support for giving the user roles, and making "Approved" a role.

    If you mean something else with approved, feel free to ignore this. :-)

    0 讨论(0)
  • 2021-02-13 23:32
    • super(UnapprovedUser, self) is wrong it should be super(UnapprovedUser, cls) because in class method you do not have self available

    • I will reiterate your question , in base class you are creating user and somehow you want to return derived class e.g.

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

    it prints User object instead of UnapprovedUser object here you want UnapprovedUser.get to return UnapprovedUser, for that you can create a factory function which wil return appropriate user and than fill it with 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")
    

    it prints UnapprovedUser object

    0 讨论(0)
  • 2021-02-13 23:33

    Rather than "casting", I think you really want to create an UnapprovedUser rather than a User when invoking UnapprovedUser.get(). To do that:

    Change User.get to actually use the cls argument that's passed-in:

    @classmethod
    def get(cls, uid):
        ldap_data = LdapUtil.get(uid + ',' + self.base_dn)
        return cls._from_ldap(ldap_data)
    

    You'll need to do something similar in _from_ldap. You didn't list the code for _from_ldap, but I assume that at some point it does something like:

    result = User(... blah ...)
    

    You want to replace this with:

    result = cls(... blah ...)
    

    Remember: in Python a class object is a callable that constructs instances of that class. So you can use the cls parameter of a classmethod to construct instances of the class used to call the classmethod.

    0 讨论(0)
  • 2021-02-13 23:36
    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))
    

    Result:

    {'a': 10, 'a_variable': 'something'}
    {'a': 10, 'a_variable': 'something', 'b': 15}
    do something A
    <class '__main__.B'>
    
    0 讨论(0)
  • 2021-02-13 23:43

    Python is a dynamically-typed language, so the concept of "casting" doesn't exist. If the object is already an UnapprovedUser, then you can already call all methods that exist in that class, without having to cast.

    0 讨论(0)
提交回复
热议问题