How do you set a condition in python based on data types?

This question seems staggeringly simple, but I can't figure it out. I know you can check data types in python, but how can you set a conditional expression based on a data type? For example, if I need to write code that sorts through a dictionary / list and concatenates all integers, how can I isolate the search to search only integers?

I think a quick example would look something like this:

y = [] for x in somelist: if type(x) == <type 'int'>: ### <--- psuedo-code line y.append(x) print sum(int(z) for z in y) 

So, for line 3, how would I set such a conditional?

+9
source share
5 answers

What about,

 if isinstance(x, int): 

but a cleaner way would be just

 sum(z for z in y if isinstance(z, int)) 
+28
source

There is really a big “it depends” on type checking in Python. There are many ways to deal with types, and everyone has their pros and cons. There are a few more with Python3.

  • Explicit Type Equality

Types are first-class objects, and you can treat them like any other value. Therefore, if you want the type of something to be equal to int , just check it:

 if type(x) == int: 

This is the most stringent type of testing: exact type equality is required. Often this is not what you want:

  • This eliminates the substitute types: and the float will not be valid, even if it behaves as an int many targets.
  • It excludes subclasses and abstract types: the pretty int type of the subclass or enum will be rejected, even if they are logically integers.
    • This severely limits portability: Python2 strings can be both str and unicode , and integers can be int and long .

Note that explicit type equality is used for low-level operations:

  • Some types cannot be subclassed, such as slice . An explicit check, well, is more explicit here.
  • Some low-level operations, such as serialization or the C-API, require certain types.

Options

Comparison can also be performed with the __class__ attribute:

 if x.__class__ == int: 

Note that if the class defines the __class__ property, it is not the same as type(x) .

When you need to test several classes, using dict to send actions is more extensible and can be faster (≥5-10 classes) than explicit checks. This is especially useful for conversions and serialization:

 dispatch_dict = {float: round, str: int, int: lambda x: x} def convert(x): converter = self.dispatch_dict[type(x)] # lookup callable based on type return converter(x) 
  • Instance validation for explicit types

The idiomatic type test uses the built-in isinstance :

 if isinstance(x, int): 

This verification is accurate and efficient. Most often, people want to check types:

  • It handles subtypes correctly. A pretty type of int print will pass this test anyway.
  • This allows you to check multiple types at once. In Python2, executing isinstance(x, (int, long)) returns all built-in integers.

Most importantly, the cons in most cases are negligible:

  • It still accepts cool subclasses that behave in a weird way. Since you can behave in a strange way, protecting yourself from this is futile.
  • This can be too restrictive: many people check isinstance(x, list) when any sequence (e.g. tuple ) or even iterative (e.g. generator ) also works. This is more for general purpose libraries than scripts or applications.

Options

If you already have a type, issubclass behaves the same way:

 if issubclass(x_type, int): 
  • Validating an instance for an abstract type

Python has the concept of abstract base classes . Simply put, they express the meaning of types, not their hierarchy:

 if isinstance(x, numbers.Real): # accept anything you can sum up 

In other words, type (x) is not necessarily inherited from numbers.Real but should behave the same. However, this is a very complex and complex concept:

  • This is often unnecessary if you are looking for basic types. An integer is just an int most cases.
  • People who come from other languages ​​often confuse his concepts.
    • Unlike C ++, the emphasis is on the abstract base class, not on the abstract base class.
    • ABCs can be used as Java interfaces, but can still have specific functionality.

However, it is incredibly useful for universal libraries and abstractions.

  • Many functions / algorithms do not need explicit types, just their behavior.
    • If you just need to search for things by key, dict limits you to a specific type in memory. In contrast, collections.abc.Mapping also includes database shells, large backup dictionaries on disk, lazy containers, ... and dict
  • This allows you to express partial type restrictions.
    • There is no strict base type that implements iteration. But if you check objects against collections.abc.Iterable , they all work in a for loop.
  • This allows you to create separate optimized implementations that look like the same abstract type.

Although this is not usually required for one-time scripts, I highly recommend using it for anything that goes beyond several releases of Python.

  • Pre conversion

The idiomatic way of handling types is not to test them, but on the assumption that they are compatible. If you already expect to introduce the wrong types, just skip anything that is not compatible:

 try: ix = int(x) except (ValueError, TypeError): continue # not compatible with int, try the next one else: a.append(ix) 

This is not really a type check, but usually serves the same purpose.

  • This ensures that you have the expected type in your products.
  • It has some limited capabilities for converting invalid types, for example, specializing float to int .
  • This works without your knowledge of which types match int .

The main disadvantage is that it is an explicit conversion.

  • You can silently accept "wrong" values, for example, convert str containing a literal.
  • It unnecessarily converts even types that are good enough, like float to int when you just need numbers.

Conversion is an effective tool for some specific use cases. This works best if you know roughly what you are doing and should give guarantees about your results.

  • Entry management

The best way to do this is to make sure you never have to check the type first. This is a bit of a meta theme, as it is highly dependent on the use case.

Here, the source of somelist should never have put no numbers in it.

+6
source

let me declare an int variable x

 x = 2 if type(x) == type(1) or isinstance(x, int): # do something 

Both work great.

0
source

Easy to use types.

 import types k = 5 if(type(k)==types.IntType): print "int" 

Here's a quick directory (types):

 ['BooleanType', 'BufferType', 'BuiltinFunctionType', 'BuiltinMethodType', 'ClassType', 'CodeType', 'ComplexType', 'DictProxyType', 'DictType', 'DictionaryType', 'EllipsisType', 'FileType', 'FloatType', 'FrameType', 'FunctionType', 'GeneratorType', 'GetSetDescriptorType', 'InstanceType', 'IntType', 'LambdaType', 'ListType', 'LongType', 'MemberDescriptorType', 'MethodType', 'ModuleType', 'NoneType', 'NotImplementedType', 'ObjectType', 'SliceType', 'StringType', 'StringTypes', 'TracebackType', 'TupleType', 'TypeType', 'UnboundMethodType', 'UnicodeType', 'XRangeType', '__builtins__', '__doc__', '__file__', '__name__', '__package__'] 
-1
source

You can use the type function on both sides of the operator. Like this:

 if type(x) == type(1): 
-1
source

All Articles