Amistad
Amistad

Reputation: 7410

Checking if a variable belongs to a class in python

I have a small class which is as follows :

class Gender(object):
    MALE = 'M'
    FEMALE = 'F'

I have a parameter variable which can be only M or F.To ensure it is only that, I do the following :

>>> parameter = 'M'
>>> if parameter not in (Gender.MALE, Gender.FEMALE)
...     print "Invalid parameter"
...
Invalid parameter
>>>

Now I have a class which contains all the States in USA as follows:

class States(object):
    ALABAMA = 'AL'
    ALASKA = 'AK'
    ARIZONA = 'AZ'
    ARKANSAS = 'AR'
    CALIFORNIA = 'CA'
    COLORADO = 'CO'
    CONNECTICUT = 'CT'
    DELAWARE = 'DE'
    DISTRICTOFCOLUMBIA = 'DC'
    ....
....

Like the example above,my parameter now is AL.However, since there are 50 states in the USA,I cannot practically use the tuple with 50 variables like I used above.Is there a better way of doing this ? I did read about isinstance but it did not give me the expected results.

Upvotes: 14

Views: 12217

Answers (4)

G M
G M

Reputation: 22529

Indeed if you can set at the beginning all your arguments it is better just to put the required arguments without default arguments. This forces the user to set the arguments. However, often you might want to set the attributes later for various reasons.

I find very handy to define a class Required that I can use as a place holder, and use a function validate before the object "is sent to production".

class Required(object):
    def __init__(self,description=None):
        self.description = description
    def __repr__(self): 
        return 'Required attribute:%s' %self.description



class MyClass(object):
    def __init__(self):
        self.ID = Required(self.ID = Required("ID is mandatory, please set it using set_ID method."))
        self.context = None
        self.type = "MyClass"


    def set_ID(self,MyClass_ID):
        """
        The id property identifies this MyClass with the URL at which it is available online.
        """
        # check MyClass_ID is valid before assigning it
        # valid(ID)
        self.ID = MyClass_ID

    def validate(self):
        for i in self.__dict__.values():
            if isinstance(i, Required):
                print(i)
                # Warining or raise error

g = MyClass()
g.validate()

Upvotes: 0

Ian Clark
Ian Clark

Reputation: 9357

You could use the __dict__ property which composes a class, for example:

In [1]: class Foo(object):
   ...:     bar = "b"
   ...:     zulu = "z"
   ...:     
In [2]: "bar"  in Foo.__dict__
Out[2]: True

Or as you're searching for the values use __dict__.values():

In [3]: "b" in Foo.__dict__.values()
Out[3]: True

As Peter Wood points out, the vars() built-in can also be used to retrieve the __dict__:

In [12]: "b" in vars(Foo).values()
Out[12]: True

The __dict__ property is used as a namespace for classes and so will return all methods, magic methods and private properties on the class as well, so for robustness you might want to modify your search slightly to compensate.

In your case, you might want to use a classmethod, such as:

class States(object):
    ALABAMA = "AL"
    FLORIDA = "FL"

    @classmethod
    def is_state(cls, to_find):
        print(vars(cls))
        states = [val for key, val in vars(cls).items()
                  if not key.startswith("__")
                  and isinstance(val, str)]
        return to_find in states

States.is_state("AL") # True
States.is_state("FL") # True
States.is_state("is_state") # False
States.is_state("__module__") # False

Update This clearly answer's the OPs question, but readers may also be interested in the Enum library in Python 3, which would quite possibly be a better container for data such as this.

Upvotes: 16

Forge
Forge

Reputation: 6844

I would suggest using Enum to define both Gender and States.
Enum if part of the standard library on Python 3. If you are on Python 2 use enum34, install with pip install enum34.

from enum import Enum
class States(Enum):
    ALABAMA = 'AL'
    ALASKA = 'AK'
    ARIZONA = 'AZ'
    ARKANSAS = 'AR'
    CALIFORNIA = 'CA'
    COLORADO = 'CO'
    CONNECTICUT = 'CT'
    DELAWARE = 'DE'
    DISTRICTOFCOLUMBIA = 'DC'
    ...

Then you can check if a variable is one of the states by

isinstance(variable, States)

Upvotes: 5

Burhan Khalid
Burhan Khalid

Reputation: 174728

Why don't you use a dictionary? Its a lot simpler and lookups will be easier as well.

states = {'AL': 'Alabama', 'AK': 'Alaska' ... }
test_state = 'Foo'

if test_state not in states.keys():
    print('{} is not valid input'.format(test_state))

Upvotes: 6

Related Questions