Open Side Menu Go to the Top
Register
** Python Support Thread ** ** Python Support Thread **

06-02-2011 , 09:16 AM
Quote:
Originally Posted by Neil S
Bash IDEs all you want but please, please learn there's more to debugging than print statements. Sometimes a full debugger is overkill... but sometimes a debugger is the only way.
Indeed. If someone told me that they never used a debugger... I wouldn't work with that person.

And this is coming from someone that uses Print statements way too often.
** Python Support Thread ** Quote
06-02-2011 , 10:57 AM
Quote:
Originally Posted by ralu
You do not need IDE. In case you need to debug you can use print function. This by far best and superior way for writing programs.

For simple editor you can use IDLE (it comes whit python distribution), but if you really think that you can not live without VisualStudio look like software, debugger and code completion try using Eclipse whit Pydev plugin.
What the hell? Isn't half the reason why python is awesome is the PDB module and the add-ons you can use with it? Do you really just use print statements over PDB? Really?
** Python Support Thread ** Quote
06-02-2011 , 02:57 PM
After messing with it a bit, I figured out that I can develop .py files and then execute them directly from the cmd line. Simple!
** Python Support Thread ** Quote
06-02-2011 , 06:13 PM
Quote:
Originally Posted by jjshabado
Indeed. If someone told me that they never used a debugger... I wouldn't work with that person.

And this is coming from someone that uses Print statements way too often.
Ditto. I'll print/NSLog/whatever all day long. But when you need the debugger.. well, just use it. It's not hard.
** Python Support Thread ** Quote
06-08-2011 , 10:19 PM
Quote:
Originally Posted by ralu
You do not need IDE. In case you need to debug you can use print function. This by far best and superior way for writing programs.
Relying on print statements for debugging anything of increasing complexity can become a bad habit, according to what I've learned.

I do agree that an IDE is not critical though, but it can be convenient. I prefer Emacs, but I also use an IDE too.

Wing IDE is a Python specific IDE that's free for non-commercial purposes. It doesn't have any overhead to setting it up (unlike Eclipse), so it can be good for beginners. And Eclipse has already been mentioned.
** Python Support Thread ** Quote
06-09-2011 , 12:07 PM
What type of debugger do you use with Python? Is there a program that will allow you to step through instructions and inspect values along the way?
** Python Support Thread ** Quote
06-09-2011 , 12:08 PM
http://docs.python.org/library/pdb.html

My most common use case is just sticking:

import pdb
pdb.set_trace()

wherever I want to jump into the code.
** Python Support Thread ** Quote
06-10-2011 , 01:02 PM
ok am i losing my mind, or is this behavior just absurdly ******ed?

(yes, i appreciate the irony of my printf debugging considering the above discussion, but i'm trying to demonstrate a point.)

Code:
#!/usr/bin/env python

list = [1, 'a', 'b', 'c', 4]
for item in list:
    print "list before: %s" % list
    try:
        item = int(item)
    except ValueError:
        print "%s cannot be cast to int. Delete it." % item
        list.remove(item)
    else:
        print "%s looks like an int. No problem, mon." % item
    print "list after : %s" % list
    print

print "### final list is %s" % list
seems straightforward to me. however...

Spoiler:

Code:
list before: [1, 'a', 'b', 'c', 4]
1 looks like an int. No problem, mon.
list after : [1, 'a', 'b', 'c', 4]

list before: [1, 'a', 'b', 'c', 4]
a cannot be cast to int. Delete it.
list after : [1, 'b', 'c', 4]

list before: [1, 'b', 'c', 4]
c cannot be cast to int. Delete it.
list after : [1, 'b', 4]

### final list is [1, 'b', 4]
in other words, when i delete 'a' from list, the for loop doesn't notice and ends up skipping the next entry (since it moved back a slot after i deleted 'a'). i can draw a pointer diagram of what i think is happening if that will help .



is there some simple workaround to this problem? do i need to make a separate clone of list for purposes of iterating? ugh, python.
** Python Support Thread ** Quote
06-10-2011 , 01:08 PM
Messing with a list while you iterate through it is generally a bad idea, and that's not python-specific.
** Python Support Thread ** Quote
06-10-2011 , 01:15 PM
i mean, sure, i guess. i guess i don't know enough about how python handles its iterators internally to have an expectation that this would work.

that said, i feel like this pattern works fine in other languages. maybe i'm just losing my mind, as alluded to in my previous post .

edit: adding list_copy = copy.deepcopy(list) and iterating on that seems to solve the problem. i think the real solution is to use map/apply/whatever-the-****-python-calls-it with a lambda or small function, but i don't think it will greatly improve efficiency and it will probably hurt readability.
** Python Support Thread ** Quote
06-10-2011 , 01:41 PM
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.
** Python Support Thread ** Quote
06-10-2011 , 06:40 PM
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.
** Python Support Thread ** Quote
06-11-2011 , 02:54 PM
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.
** Python Support Thread ** Quote
06-11-2011 , 06:49 PM
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.
** Python Support Thread ** Quote
06-11-2011 , 09:35 PM
Has anyone here used the C API? I'm having trouble calling a C function from another C function.
** Python Support Thread ** Quote
06-12-2011 , 01:27 AM
maybe just post some code and see if anyone bites?
** Python Support Thread ** Quote
06-12-2011 , 02:19 PM
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.
** Python Support Thread ** Quote
06-12-2011 , 02:41 PM
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?
** Python Support Thread ** Quote
06-12-2011 , 02:50 PM
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.
** Python Support Thread ** Quote
06-12-2011 , 05:55 PM
This reminds me that I shouldn't have put C on my resume.
** Python Support Thread ** Quote
06-13-2011 , 09:15 AM
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.
** Python Support Thread ** Quote
06-13-2011 , 11:30 AM
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
** Python Support Thread ** Quote
06-13-2011 , 11:34 AM
That doesn't work since you can't call isdigit on an integer.
** Python Support Thread ** Quote
06-13-2011 , 11:38 AM
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]
** Python Support Thread ** Quote
06-13-2011 , 11:44 AM
Do people feel the list comprehension is better than using filter here? Seems weird to me.
** Python Support Thread ** Quote

      
m