Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type check should use isinstance instead of type() is #91

Closed
truebit opened this issue Oct 16, 2019 · 11 comments · Fixed by #92
Closed

type check should use isinstance instead of type() is #91

truebit opened this issue Oct 16, 2019 · 11 comments · Fixed by #92

Comments

@truebit
Copy link
Contributor

truebit commented Oct 16, 2019

I saw all the type check in this libary using type(xxx) is/is not.
I suggest using another built-in function: isinstance.

The main difference here is that isinstance also returns True for subclasses. More details could be found here: What are the differences between type() and isinstance()?

I got a subclass derived from dict, objectpath would raise an error.
change interpreter.py line 44 using isinstance would fix the bug.

  def setData(self, obj):
    if isinstance(obj, tuple(ITER_TYPES + [dict])):
      self.data = obj
@adriank
Copy link
Owner

adriank commented Oct 16, 2019

Hi,

Last time I checked, isinstance was making ObjectPath significantly slower. If you do performance tests and the difference isn't so drastic nowadays, I'll accept your PR.

Best,
Adrian

@truebit
Copy link
Contributor Author

truebit commented Oct 17, 2019

Oh, I did not realize the performance issue. If so, I think we should narrow down the issue to setData method itself.
If we agree to support subclasses in objectpath, we could change this method using isinstance.

@truebit
Copy link
Contributor Author

truebit commented Oct 17, 2019

concerning about the performance, here below is my testing results:

environment:
python2 version: 2.7.16
python3 version : 3.7.4
both installed via brew
Mac OS X version: 10.14.6 (18G103)

result: all in 10**6 loop of 3 times with time unit microseconds (usec)

# python2 with type/isinstance diff
python2 -m timeit -n 1000000 'type("A") in (list,basestring)'
1000000 loops, best of 3: 0.143 usec per loop

python2 -m timeit -n 1000000 'isinstance("A", (list,str))'
1000000 loops, best of 3: 0.234 usec per loop

# python3 with type/isinstance diff
python3 -m timeit -r 3 -n 1000000 -u usec  'type("A") in (list,str)'
1000000 loops, best of 3: 0.179 usec per loop

python3 -m timeit -r 3 -n 1000000 -u usec  'isinstance("A", (list,str))'
1000000 loops, best of 3: 0.188 usec per loop

# python2/3 multiple type check. isinstance only support tuple
python3 -m timeit -r 3 -n 1000000 -u usec  'type("A") in [list,str]'
1000000 loops, best of 3: 0.208 usec per loop

python2 -m timeit -n 1000000 'type("A") in [list,str]'
1000000 loops, best of 3: 0.212 usec per loop

# python2/3 multiple type check using + in list
python2 -m timeit -n 1000000 'type("A") in [list,str]+[int]'
1000000 loops, best of 3: 0.52 usec per loop
python3 -m timeit -r 3 -n 1000000 -u usec  'type("A") in [list,str]+[int]'
1000000 loops, best of 3: 0.34 usec per loop

If microseconds level performance is a problem, I think we should also consider using tuple instead of list or even plus to do type check

@adriank
Copy link
Owner

adriank commented Oct 17, 2019 via email

@adriank
Copy link
Owner

adriank commented Oct 17, 2019 via email

@truebit
Copy link
Contributor Author

truebit commented Oct 18, 2019

I tried on my local machine, all tests passed. Could you please list which tests failed?

@adriank
Copy link
Owner

adriank commented Oct 18, 2019 via email

@truebit
Copy link
Contributor Author

truebit commented Oct 18, 2019 via email

@adriank
Copy link
Owner

adriank commented Oct 18, 2019 via email

@truebit
Copy link
Contributor Author

truebit commented Oct 21, 2019

I saw it throws TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
on lineif isinstance(obj, tuple(ITER_TYPES + [dict])).

It's due to the python 2 handling process on map and filter. Actually something like type(map(string.lower, 'ABC')) is map is alsoFalse in python2, but covered by the in list check.

The NameError would only raise when it's python 1 for map and filter.
What's your opinion to fix this problem? Using Python version check maybe a good solution.

@truebit
Copy link
Contributor Author

truebit commented Oct 21, 2019

I created a PR #93 to fix this failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants