Agnostic means of identifying a member
I see 2 approaches to this:


Allow Member to be initialized with a dictionary.
Allow your Member class to behave like a dictionary.


If you proceed by approach 1, then your resulting code will be very concise:

if isinstance(member, Member):
    return member.identification()
else if isinstance(member, dict):
    member = Member(member)
    return member.identification()
raise ValueError('no identification could be made')


But you will have a lot of additional logic in Member

Alternatively, if you do not like that approach, we can make Member work like a dictionary. Basically member['guid'] would refer to member.guid if member is a Member or the dictionary version if member is a dictionary.

We can do this by adding some magic methods to Member: __getitem__(self, key): and __setitem__(self, key, val): and __contains__(self, val):. The code would look something like this:

def __getitem__(self, key):
    if key == "nickname":
        return self.nickname
    elif key == "guid":
        return self.guid
    # and so on

def __setitem(self, key, val):
    if key == "nickname":
        self.nickname = val
    elif key == "guid":
        self.guid = val
    # and so on

def __contains__(self, val):
    if val == "guid":
        return self.guid != None
    elif val == "user_id":
        return self.user_id != None
    # and so on


This would make code snippet something like this:

try:
    return member.identification()
except AttributeError:
    pass

if not isinstance(member, Member) and not isinstance(member, dict):
    raise ValueError('no identification could be made')

id_types = ['user_id', 'email', 'phone_number']
if 'guid' not in member:
    member['guid'] = cls._next_guid()
for idt in id_types:
    if idt in member:
        try:
            return {
                'nickname': member['nickname'],
                'guid': member['guid'],
                 idt: member[idt]
            }
        except KeyError:
            raise ValueError('no nickname')
 else:
    raise ValueError('no user_id, email, or phone_number')