|
|
| Programming Discussions about computer programming |
06-10-2011, 01:41 PM
|
#61
|
|
Carpal \'Tunnel
Join Date: Jul 2006
Posts: 11,092
|
Re: ** Python Support Thread **
Quote:
Originally Posted by Neil S
Messing with a list while you iterate through it is generally a bad idea, and that's not python-specific.
|
Absolutely this. It'll definitely give you problems in Java (when I was a TA we had an assignment that constantly generated problems like this).
Edit:
And yes, you probably just want:
filter(lambda x: type(x) == int, list)
Edit again:
I'd consider this more readable. But that's pretty subjective. Especially since lots of stuff is considered readable by regular python users that isn't readable by people not use to it.
|
|
|
06-10-2011, 06:40 PM
|
#62
|
|
ɹǝʍoʇpunoɹ
Join Date: Feb 2005
Location: soah made my profile
Posts: 13,926
|
Re: ** Python Support Thread **
Quote:
Originally Posted by jjshabado
Absolutely this. It'll definitely give you problems in Java (when I was a TA we had an assignment that constantly generated problems like this).
Edit:
And yes, you probably just want:
filter(lambda x: type(x) == int, list)
Edit again:
I'd consider this more readable. But that's pretty subjective. Especially since lots of stuff is considered readable by regular python users that isn't readable by people not use to it.
|
I like maps and filters and lambdas but actually I don't think this is the "pythonic" way to do something. You are transforming a list into another list, therefore you should expect to be able to use a list comprehension here.
so something like:
Code:
list = [el for el in list if type(el) == int]
to do what you were suggesting. It doesn't have the same behaviour as tyler_cracker expected, though, because it doesn't convert floats or strings or other things that can be converted to integers.
So maybe something like
Code:
def convertable(x):
try: return int(x)
except ValueError: return None
list = [el for el in list if convertable(x) is not None]
By the way, I wouldn't use the name "list" either for the variable, it is legal Python code but you are shadowing the builtin list function and this might do something unexpected, particularly if the current function/method has more code in it.
|
|
|
06-11-2011, 02:54 PM
|
#63
|
|
Carpal \'Tunnel
Join Date: Apr 2005
Location: Shallow End OTKP
Posts: 13,918
|
Re: ** Python Support Thread **
Quote:
Originally Posted by RoundTower
I like maps and filters and lambdas but actually I don't think this is the "pythonic" way to do something. You are transforming a list into another list, therefore you should expect to be able to use a list comprehension here.
so something like:
Code:
list = [el for el in list if type(el) == int]
to do what you were suggesting. It doesn't have the same behaviour as tyler_cracker expected, though, because it doesn't convert floats or strings or other things that can be converted to integers.
|
i am far from an authority on how to make something look pythonic -- i come from perl and would rather use ruby and i will never find it intuitive to say str(object) instead of object.str() (though i understand why python does it that way). that said, i find the list comprehension form to be harder to understand than other representations. especially since, as you mentioned, i need to cast the things to ints, not simply throw away things that aren't ints.
Quote:
So maybe something like
Code:
def convertable(x):
try: return int(x)
except ValueError: return None
list = [el for el in list if convertable(x) is not None]
|
if we were on SO, this is the one i'd choose as The Answer.
"is not None" is another of those python things i feel i will never get used to.
Quote:
|
By the way, I wouldn't use the name "list" either for the variable, it is legal Python code but you are shadowing the builtin list function and this might do something unexpected, particularly if the current function/method has more code in it.
|
that was just example code, but good point for the audience.
|
|
|
06-11-2011, 06:49 PM
|
#64
|
|
ɹǝʍoʇpunoɹ
Join Date: Feb 2005
Location: soah made my profile
Posts: 13,926
|
Re: ** Python Support Thread **
except I got it wrong, of course! I made a typo and a bad error.
because you need to be able to cast other things to integers, it needs to behave like
Code:
def convertable(x):
try: return int(x)
except ValueError: return None
list = [int(el) for el in list if convertable(el) is not None]
but that is unnecessarily ugly, it calls int() twice for every element. I'm not sure how to solve this in a nice way after all.
Last edited by RoundTower; 06-11-2011 at 07:06 PM.
|
|
|
06-11-2011, 09:35 PM
|
#65
|
|
veteran
Join Date: Jul 2004
Posts: 2,165
|
Re: ** Python Support Thread **
Has anyone here used the C API? I'm having trouble calling a C function from another C function.
|
|
|
06-12-2011, 01:27 AM
|
#66
|
|
Carpal \'Tunnel
Join Date: Apr 2005
Location: Shallow End OTKP
Posts: 13,918
|
Re: ** Python Support Thread **
maybe just post some code and see if anyone bites?
|
|
|
06-12-2011, 02:19 PM
|
#67
|
|
veteran
Join Date: Jul 2004
Posts: 2,165
|
Re: ** Python Support Thread **
Ok then. I've used the C API a lot before, and it's basically coding in C with a little gymnastics to pass values between C and python. I'm doing some project euler now to brush up on those skills now while I'm unemployed.
So this function takes int n and returns a list of all the factors of n (it's not complete yet, just the relevant code that's spitting out errors is here). isPrime returns True or False. I'm trying to check if n is prime before I try to factor it.
Code:
static PyObject *
euler_Factors(PyObject *self, PyObject *args){
long n, i;
int test;
PyObject *res;
if(!PyArg_Parse(args,"(l)",&n))
return NULL;
res = PyEval_CallFunction(euler_isPrime, "i", n);
if(!(test = PyObject_IsTrue(res)))
return NULL;
printf("%d\n",test);
return res;
}
Code:
static PyObject *
euler_isPrime(PyObject *self, PyObject *args){
unsigned long long n, i, r;
if(!PyArg_Parse(args,"(l)",&n))
return NULL;
r = (unsigned long long) (sqrt((double) (n))+1.0);
if(n<2){
Py_RETURN_FALSE;
}
else{
for(i=3;i<r;i++){
if(n%i == 0)
Py_RETURN_FALSE;
}
Py_RETURN_TRUE;
}
}
The problem is in
Code:
res = PyEval_CallFunction(euler_isPrime, "i", n);
I don't know what it's returning and can't figure out how to. It's obviously not returning Py_True or Py_False. When I compile the lib I get this warning message
Code:
euler.c:71: warning: passing argument 1 of ‘PyEval_CallFunction’ from incompatible pointer type
/usr/include/python2.6/ceval.h:21: note: expected ‘struct PyObject *’ but argument is of type ‘struct PyObject * (*)(struct PyObject *, struct PyObject *)’
It's obviously the wrong type, but I don't get how you're supposed to call a function without arguments.
|
|
|
06-12-2011, 02:41 PM
|
#68
|
|
Carpal \'Tunnel
Join Date: Apr 2005
Location: Shallow End OTKP
Posts: 13,918
|
Re: ** Python Support Thread **
no experience with c->python but i'll take a stab:
do you need to instantiate euler_isPrime before you use it? it's not clear to me where that value is coming from.
i also don't understand what you're doing with the long i and why you pass "i" to PyEval_CallFunction.
perhaps all of this is just my ignorance of the api. if so, at least we have quickly weeded out any advice i might give on this problem as useful.
edit: also did you look at ceval.h line 21 to see if that gave you any clue what was going on?
|
|
|
06-12-2011, 02:50 PM
|
#69
|
|
veteran
Join Date: Jul 2004
Posts: 2,165
|
Re: ** Python Support Thread **
Quote:
Originally Posted by tyler_cracker
no experience with c->python but i'll take a stab:
do you need to instantiate euler_isPrime before you use it? it's not clear to me where that value is coming from.
|
This is what I suspect, but it would be a minor pain to create multiple libs just so you can call one function from another.
Quote:
|
i also don't understand what you're doing with the long i and why you pass "i" to PyEval_CallFunction.
|
That's prob a little confusing. long i is declared to use later in a loop. I'm not passing i to the function. "i" is there create a type Py_Int from n.
Quote:
|
edit: also did you look at ceval.h line 21 to see if that gave you any clue what was going on?
|
Not yet. I'm still a little too hungover to dive into that.
|
|
|
06-12-2011, 05:55 PM
|
#70
|
|
ɹǝʍoʇpunoɹ
Join Date: Feb 2005
Location: soah made my profile
Posts: 13,926
|
Re: ** Python Support Thread **
This reminds me that I shouldn't have put C on my resume.
|
|
|
06-13-2011, 09:15 AM
|
#71
|
|
Carpal \'Tunnel
Join Date: Jul 2006
Posts: 11,092
|
Re: ** Python Support Thread **
Quote:
Originally Posted by RoundTower
I like maps and filters and lambdas but actually I don't think this is the "pythonic" way to do something. You are transforming a list into another list, therefore you should expect to be able to use a list comprehension here.
|
I'm far from an expert on the "Pythonic" way  , but what else is a function like filter useful for if not transforming a list?
That being said, I'd actually combine answers and define the function and put that in the filter method.
So:
Quote:
def convertible...
...
list = filter(convertible, list)
|
That seems by far the clearest answer of what you're doing. Also the easiest to test, verify correct.
|
|
|
06-13-2011, 11:30 AM
|
#72
|
|
old hand
Join Date: Apr 2008
Location: Perth, Western Australia
Posts: 1,500
|
Re: ** Python Support Thread **
Quote:
Originally Posted by RoundTower
except I got it wrong, of course! I made a typo and a bad error.
because you need to be able to cast other things to integers, it needs to behave like
Code:
def convertable(x):
try: return int(x)
except ValueError: return None
list = [int(el) for el in list if convertable(el) is not None]
but that is unnecessarily ugly, it calls int() twice for every element. I'm not sure how to solve this in a nice way after all.
|
Code:
list = [int(x) for x in list if x.isdigit()]
Last edited by sorrow; 06-13-2011 at 11:32 AM.
Reason: Forgot the cast
|
|
|
06-13-2011, 11:34 AM
|
#73
|
|
Carpal \'Tunnel
Join Date: Jul 2006
Posts: 11,092
|
Re: ** Python Support Thread **
That doesn't work since you can't call isdigit on an integer.
|
|
|
06-13-2011, 11:38 AM
|
#74
|
|
old hand
Join Date: Apr 2008
Location: Perth, Western Australia
Posts: 1,500
|
Re: ** Python Support Thread **
Quote:
Originally Posted by jjshabado
That doesn't work since you can't call isdigit on an integer.
|
Oops - just as easy though:
Code:
[x for x in list if type(x) is int]
|
|
|
06-13-2011, 11:44 AM
|
#75
|
|
Carpal \'Tunnel
Join Date: Jul 2006
Posts: 11,092
|
Re: ** Python Support Thread **
Do people feel the list comprehension is better than using filter here? Seems weird to me.
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 10:09 AM.
|