Is it possible to limit a certain variable to only certain type?

For example, i have a class named AccurateStr. How can I make sure that the variable "as" is an instance of AccurateStr?

Similarly, how can I make sure a variable is a positive int, str etc without the if statement, if that's even possible.

As far as I know, you can't limit what a variable can be. However, you can check if the variable is an instance of class by using

isinstance(arg1, arg2) # Arg1 is the variable, Arg2 is the class

That will return a truth value of True if it is an instance or False if it isn't.

Here is one way to check this ...

class C():
    pass

a = 77
print(type(a))  # <type 'int'>

b = 'hello'
print(type(b))  # <type 'str'> 

c = C()
print(type(c))  # <type 'instance'>

d = {
'one': 1, 
'two': 2
}
print(type(d))  # <type 'dict'> 

f= 3.14
print(type(f))  # <type 'float'>

q = [1, 2, 3]
print(type(q))  # <type 'list'>

# check if a variable is an int or float
for item in [1, 2.34, 'oops']:
    if type(item) in (int, float):
        print("%s is a float or integer" % item)

In a static language like C or Java, of course.
But,
doing exactly that in Python is impossible.
The closest way is to do use the above solutions.
Here's why...

:)

In Python, variables don't actually have a type.

So that's why you can do this:

x = 1
x = "1"
x = False

Did x just change type twice there?
Absolutely not.

The variable x is just a name.
In line 1, an int object 1 was created in memory,
and a name x was created in the namespace,
and it was bound to that int object in memory.

In line 2, a string object "1" was created,
and x was rebound to that object.
Python then finds that the first int 1 object is unreferenced,
so it is garbage collected.

In line three, it happens again.

So the main idea is,
the name "x" never changed,
but it was rebound to new objects twice.

That is because of Python's typing discipline (dynamic, duck, strongly).

Edited 6 Years Ago by jcao219: n/a

The Pythonic way is to not litter Python code with type checks, but to proceed as if the names refer to data of the correct type.
To aid in this, Python strives to be readable, and your functionality/coverage tests should be comprehensive.

You could force instance attributes to have a type using a descriptor

class TypedAttribute(object):
    def __init__(self, tp):
        self.tp = tp
        self.name = "_typedattr_%d" % id(self)

    def __get__(self, obj, objtype = None):
        if obj is None:
            return self
        return getattr(obj, self.name)

    def __set__(self, obj, value):
        if not isinstance(value, self.tp):
            raise TypeError, "invalid type %s" % type(value).__name__
        setattr(obj, self.name, value)

class A(object):
    foo = TypedAttribute(int)

a = A()

a.foo = 7
print a.foo
a.foo = "hello"
print a.foo

""" my output -->
7
Traceback (most recent call last):
  File "./tpattr.py", line 24, in <module>
    a.foo = "hello"
  File "./tpattr.py", line 14, in __set__
    raise TypeError, "invalid type %s" % type(value).__name__
TypeError: invalid type str
"""

Edited 6 Years Ago by Gribouillis: n/a

The Pythonic way is to not litter Python code with type checks, but to proceed as if the names refer to data of the correct type.
To aid in this, Python strives to be readable, and your functionality/coverage tests should be comprehensive.

That is absolutely correct.
"when I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."
An objects usability is determined not by its actual type, but by its methods, properties, etc.

That is the beauty of Python.
So I would encourage you to code pythonically.

This question has already been answered. Start a new discussion instead.