How do you set a conditional in python based on datatypes?
This question seems mind-boggling simple, yet I can't figure it out. I know you can check datatypes in python, but how can you set a conditional based on the datatype? For instance, if I have to write a code that sorts through a dictionary/list and adds up all the integers, how do I isolate the search to look for only integers?
I guess 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?
How about,
if isinstance(x, int):
but a cleaner way would simply be
sum(z for z in y if isinstance(z, int))
There is a really big "it depends" to type-checking in Python. There are many ways to deal with types, and all have their pros and cons. With Python3, several more have emerged.
Types are first-class objects, and you can treat them like any other value. So if you want the type of something to be equal to int
, just test for it:
if type(x) == int:
This is the most restrictive type of testing: it requires exact type equality. Often, this is not what you want:
float
would not be valid, even though it behaves like an int
many purposes. int
subclass or enum
would be rejected, even though they are logically Integers. str
or unicode
, and Integers can be either int
or long
. Note that explicit type equality has its uses for low-level operations:
slice
. An explicit check is, well, more explicit here. Variants
A comparison is slightly faster when performed with __class__
:
if x.__class__ == int:
When there are multiple classes to check for, using a dict
to dispatch actions is considerably faster than explicit checks. This is especially useful for conversions and serialisation:
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)
The idiomatic type test uses the isinstance
builtin:
if isinstance(x, int):
This check is both exact and performant. This is most often what people want for checking types:
int
subclass would still pass this test. isinstance(x, (int, long))
gets you all builtin integers. Most importantly, the downsides are negligible most of the time:
isinstance(x, list)
when any sequence (eg tuple
) or even iterable (eg a generator
) would do as well. This is more of a concern for general purpose libraries than scripts or applications. Variants
If you already have a type, issubclass
behaves the same:
if issubclass(x_type, int):
Python has a concept of abstract base classes. Loosely speaking, these express the meaning of types, not their hierarchy:
if isinstance(x, numbers.Real): # accept anything you can sum up
In other words, type(x) does not necessarily inherit from numbers.Real
but must behave like it. Still, this is a very complex and difficult concept:
int
most of the time. However, it is incredibly useful for generic libraries and abstractions.
dict
restricts you to a specific in-memory type. By contrast, collections.abc.Mapping
also includes database wrappers, large disk-backed dictionaries, lazy containers, ..., and dict
. collections.abc.Iterable
, they all work in a for
loop. While it is usually not needed for throwaway scripts, I would highly recommend using this for anything that lives beyond a few python releases.
The idiomatic way of handling types is not to test them, but to assume they are compatible. If you already expect some wrong types in your input, simply skip everything 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 actually a type check, but usually serves the same intention.
float
to int
. int
. The major downside is that it is an explicit transformation.
str
containing a literal. float
to int
when you just need numbers. Conversion is an effective tool for some specific use cases. It works best if you know roughly what your input is, and must make guarantees about your output.
The best course of action is to ensure you never have to check for type in the first place. This is a bit of a meta-topic, as it depends strongly on the use case.
Here, the source of somelist
should never have put non-numbers into it.
Easy - use types.
import types
k = 5
if(type(k)==types.IntType):
print "int"
Here's a quick dir(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__']
链接地址: http://www.djcxy.com/p/54242.html
上一篇: 抽象类和接口之间有什么区别?