Passing arguments to function - (The fundamentals are confusing me)

Discussion in 'Python' started by =?ISO-8859-1?Q?Gregory_Pi=F1ero?=, Aug 9, 2005.

  1. Hey guys, would someone mind giving me a quick rundown of how
    references work in Python when passing arguments into functions? The
    code below should highlight my specific confusion:

    <code>

    bool1=True
    lst1=[1,2,3]

    def func1(arg1): arg1.append(4)

    def func2(arg1): arg1=False

    >>func1(lst1)
    >>lst1

    [1,2,3,4]

    >>func2(bool1)
    >>bool1

    True

    </code>

    Why does my list variable get changed for the rest of the program, but
    my boolean variable doesn't. What am I not understanding?

    --
    Gregory Piñero
    Chief Innovation Officer
    Blended Technologies
    (www.blendedtechnologies.com)
    =?ISO-8859-1?Q?Gregory_Pi=F1ero?=, Aug 9, 2005
    #1
    1. Advertising

  2. Re: Passing arguments to function - (The fundamentals are confusingme)

    Gregory Piñero wrote:
    > Hey guys, would someone mind giving me a quick rundown of how
    > references work in Python when passing arguments into functions? The
    > code below should highlight my specific confusion:


    All arguments are passed by reference, but in Python equality rebinds
    the name.

    >
    > <code>
    >
    > bool1=True
    > lst1=[1,2,3]
    >
    > def func1(arg1): arg1.append(4)


    In C++, pretending it had dynamic typing, this would be equivalent to:
    void func1( * arg1){
    arg1->append(4);
    }

    >
    > def func2(arg1): arg1=False

    void func2 ( * arg2) {
    arg2 = &(False);

    > Why does my list variable get changed for the rest of the program, but
    > my boolean variable doesn't. What am I not understanding?


    In Python, "x = y" has a very definite meaning of "y is assigned to the
    name of x." This change does not affect whatever was in x to start
    with, and it certainly would not affect anything else which holds a
    reference to the object formerly known as x.

    In contrast, calling a function which mutates the object (like .append
    on lists, or assignment by lst[index]=something) actually changes the
    object itself, which is of course reflected by all other names that hold
    a reference to the object.
    Christopher Subich, Aug 9, 2005
    #2
    1. Advertising

  3. Re: Passing arguments to function - (The fundamentals are confusingme)

    Christopher Subich wrote:
    > Gregory Piñero wrote:
    >
    >> Hey guys, would someone mind giving me a quick rundown of how
    >> references work in Python when passing arguments into functions? The
    >> code below should highlight my specific confusion:


    This URL is always tossed out:

    http://starship.python.net/crew/mwh/hacks/objectthink.html

    > All arguments are passed by reference, but in Python equality rebinds
    > the name.


    Bingo

    >> Why does my list variable get changed for the rest of the program, but
    >> my boolean variable doesn't. What am I not understanding?


    Booleans are immutable, lists are mutable. You change (mutate) the same
    list, but you are referencing a different (immutable) Bool

    > In Python, "x = y" has a very definite meaning of "y is assigned to the
    > name of x."


    Change it to "the object referenced by y is assigned to the name of x",
    and you're closer to the truth.
    Rocco Moretti, Aug 9, 2005
    #3
  4. =?ISO-8859-1?Q?Gregory_Pi=F1ero?=

    infidel Guest

    > in Python equality rebinds the name

    Assignment (=) rebinds the name. Equality (==) is something else
    entirely.
    infidel, Aug 9, 2005
    #4
  5. On Tue, 9 Aug 2005 10:53:15 -0400, Gregory Piñero <>
    declaimed the following in comp.lang.python:

    <rhetorical> Is this the third time this week that this has come
    up?

    > Hey guys, would someone mind giving me a quick rundown of how
    > references work in Python when passing arguments into functions? The
    > code below should highlight my specific confusion:
    >

    They work just like they do everywhere else...

    Read the manuals on mutable and immutable objects. (I'd suggest
    language reference chapter 3 and 4, library reference chapter 2.3.6,
    2.3.7)

    "names" in Python are movable labels attached to objects; they
    are not fixed locations in memory to which object are copied; hence they
    do not behave like variables in traditional languages.

    >
    > bool1=True


    immutable object -- "bool1" is a label attached to a fixed
    object

    > lst1=[1,2,3]
    >

    mutable object -- "lst1" is a label attached to a box
    containing objects

    > def func1(arg1): arg1.append(4)
    >


    "arg1" is a label attached to whatever object was passed in...
    .append is an operation that changes what is /inside/ that
    object

    > def func2(arg1): arg1=False
    >

    "arg1" is a label attached to whatever was passed in...
    Assignment (especially of an immutable object) takes that label
    OFF of the object that was passed in, and moves it the object of the
    assignment. It does not move the label that is outside the call.

    > >>func1(lst1)
    > >>lst1

    > [1,2,3,4]
    >

    "lst1" is the label of the box; inside of func1, that box has
    two labels: "lst1" and "arg1". You used the "arg1" label to locate the
    box, and then you changed what was inside the box. Outside the function,
    you used the "lst1" label to find the /same/ box and report what was
    inside it.

    > >>func2(bool1)
    > >>bool1

    > True
    >

    "bool1" is the label of a non-box -- a "true". Inside the
    function "true" has initially two labels: "bool1" and "arg1". You then
    moved the "arg1" label from "true" to a different object "false".
    "bool1" does not move, and still references the "true".


    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Home Page: <http://www.dm.net/~wulfraed/> <
    > Overflow Page: <http://wlfraed.home.netcom.com/> <
    Dennis Lee Bieber, Aug 9, 2005
    #5
  6. Re: Passing arguments to function - (The fundamentals are confusingme)

    Ahh, so it's a mutable thing. That makes sense that I can't change a
    mutable object and thus can't affect it outside of the function. Does
    that mean Python functions aren't always byref, but are sometimes
    byval for nonmutables?

    -Greg


    On 8/9/05, Dennis Lee Bieber <> wrote:
    > On Tue, 9 Aug 2005 10:53:15 -0400, Gregory Piñero < >
    > declaimed the following in comp.lang.python:
    >
    > <rhetorical> Is this the third time this week that this has come
    > up?
    >
    > > Hey guys, would someone mind giving me a quick rundown of how
    > > references work in Python when passing arguments into functions? The
    > > code below should highlight my specific confusion:
    > >

    > They work just like they do everywhere else...
    >
    > Read the manuals on mutable and immutable objects. (I'd suggest
    > language reference chapter 3 and 4, library reference chapter 2.3.6,
    > 2.3.7)
    >
    > "names" in Python are movable labels attached to objects; they
    > are not fixed locations in memory to which object are copied; hence they
    > do not behave like variables in traditional languages.
    >
    > >
    > > bool1=True

    >
    > immutable object -- "bool1" is a label attached to a fixed
    > object
    >
    > > lst1=[1,2,3]
    > >

    > mutable object -- "lst1" is a label attached to a box
    > containing objects
    >
    > > def func1(arg1): arg1.append(4)
    > >

    >
    > "arg1" is a label attached to whatever object was passed in...
    > .append is an operation that changes what is /inside/ that
    > object
    >
    > > def func2(arg1): arg1=False
    > >

    > "arg1" is a label attached to whatever was passed in...
    > Assignment (especially of an immutable object) takes that label
    > OFF of the object that was passed in, and moves it the object of the
    > assignment. It does not move the label that is outside the call.
    >
    > > >>func1(lst1)
    > > >>lst1

    > > [1,2,3,4]
    > >

    > "lst1" is the label of the box; inside of func1, that box has
    > two labels: "lst1" and "arg1". You used the "arg1" label to locate the
    > box, and then you changed what was inside the box. Outside the function,
    > you used the "lst1" label to find the /same/ box and report what was
    > inside it.
    >
    > > >>func2(bool1)
    > > >>bool1

    > > True
    > >

    > "bool1" is the label of a non-box -- a "true". Inside the
    > function "true" has initially two labels: "bool1" and "arg1". You then
    > moved the "arg1" label from "true" to a different object "false".
    > "bool1" does not move, and still references the "true".
    >
    >
    > --
    > > ============================================================== <
    > > | Wulfraed Dennis Lee Bieber KD6MOG <
    > > | Bestiaria Support Staff <
    > > ============================================================== <
    > > Home Page: <http://www.dm.net/~wulfraed/ > <
    > > Overflow Page: <http://wlfraed.home.netcom.com/ > <

    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >



    --
    Gregory Piñero
    Chief Innovation Officer
    Blended Technologies
    (www.blendedtechnologies.com)
    =?ISO-8859-1?Q?Gregory_Pi=F1ero?=, Aug 9, 2005
    #6
  7. =?ISO-8859-1?Q?Gregory_Pi=F1ero?=

    Dan Guest

    Re: Passing arguments to function - (The fundamentals areconfusing me)

    > Does that mean Python functions aren't always byref,
    > but are sometimes byval for nonmutables?


    Don't think of it as byref or byval (as they are used in Visual Basic).
    All parameters are passed the same way: by reference instead of by copy.

    It's a little difficult to get your head around, but I promise that once
    you understand it it will seem simple and intuitive.

    def reassign(x):
    x = ['foo']

    "reassign" has no effect, even on a mutable type like a list. It simply
    changes what "x" refers to, which isn't very useful because the name "x"
    only exists inside the function.

    In Python everything is treated the same way. Even integers are objects:

    >>> n = 1
    >>> n.__hex__()

    '0x1'

    What other programming languages do you know? Maybe we can draw a
    comparison to something you're familiar with.

    --
    Presumably, we're all fully qualified computer nerds here,
    so we are allowed to use "access" as a verb. Be advised,
    however, that the practice in common usage drives
    English-language purists to scowling fidgets.
    - from Sybex's "Perl, CGI and JavaScript", p. 256
    Dan, Aug 9, 2005
    #7
  8. Re: Passing arguments to function - (The fundamentals are confusingme)

    Gregory Piñero wrote:
    > Ahh, so it's a mutable thing. That makes sense that I can't change a
    > mutable object and thus can't affect it outside of the function.


    If you meant "immutable" for the second mutable, you're right.

    > Does
    > that mean Python functions aren't always byref, but are sometimes
    > byval for nonmutables?


    It'd probably do you good to get away from the by reference/by value
    thinking. Python isn't C/Basic/Fortran/etc.

    Variables in Python are names. They aren't the cubbyholes into which you
    put values, they are sticky notes on the front of the cubby hole.

    Parameter passing in Python always work the same way - you create a new
    name pointing to the passed object. Fin.

    The confusion you're having isn't in parameter passing, it's in the
    difference between assignment and mutation. Mutation changes the object
    itself (what's in the cubby hole), so it doesn't matter what or how many
    names/variables it has (what sticky notes are on the front). Assigment
    just changes where names point, not the contents of objects. (It's
    moving that sticky note, and only that sticky note, from one cubby to a
    different one.) Assignment justs affects that name, not any other name
    which point to the same object, including the variables in the passing
    scope.
    Rocco Moretti, Aug 9, 2005
    #8
  9. On Tue, 09 Aug 2005 10:39:29 -0500, Rocco Moretti
    <> declaimed the following in comp.lang.python:

    >
    > Change it to "the object referenced by y is assigned to the name of x",
    > and you're closer to the truth.


    In a more simplistic view, I'd reverse the phrasing... The name
    "x" is assigned to the object "y" (implying it is no longer attached to
    whatever used to have the name)
    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Home Page: <http://www.dm.net/~wulfraed/> <
    > Overflow Page: <http://wlfraed.home.netcom.com/> <
    Dennis Lee Bieber, Aug 9, 2005
    #9
  10. On Tue, 9 Aug 2005 12:32:15 -0400, Gregory Piñero <>
    declaimed the following in comp.lang.python:

    > Ahh, so it's a mutable thing. That makes sense that I can't change a
    > mutable object and thus can't affect it outside of the function. Does
    > that mean Python functions aren't always byref, but are sometimes
    > byval for nonmutables?
    >

    Reverse: boolean constants are immutable and can not be changed,
    you can only move the name used to access on to some other object.

    If you want to try relating to Visual Basics "byref" "byval",
    then they are neither. They are closer to a "copy reference"; changes to
    the /reference copy/ do not propagate back out... Changes to the item
    the reference, uh, references, do propagate out.

    And it doesn't matter what they are referencing... If it is an
    object that lets you "go inside to make changes" it is a mutable object,
    and operations that "go inside" make no changes to the "reference"
    itself.

    def sample(l1, l2, l3):
    l1.append(4)
    l2 = [l2, 4]
    l3[1] = 4

    a = [1, 2]
    b = [3, 4]
    c = [5, 6]
    sample(a, b, c)

    The first line is NOT changing the l1 reference, it is going
    inside l1 and changing the insides. "l1" and "a" BOTH reference a list
    object that started with [1, 2]. The append opened that object, and
    jammed the 4 into it... "a" and "l1" still reference the same list
    object, but the list object now has [1, 2, 4]

    The second line, OTOH, is changing the l2 reference; it is
    creating a new list containing a reference to the object that l2 is
    attached to and a reference to a constant 4, THEN it is saying the l2
    NOW references the new list -- but since the name l2 only exists inside
    the function, it doesn't affect the outside world... "l2" and "b"
    initially reference the list object [3, 4]. The assignment first creates
    a new list (with no references) of [reference to [3, 4], 4], then "l2"
    is changed from a reference to [3, 4] to be a reference to [reference to
    [3, 4], 4]; "b" is still a reference to [3, 4]

    The third one, again, is opening the referenced object. "c" and
    "l3" are references to a list containing [5, 6], "l3[1]" opens the list
    and makes the second element 4. "l3" and "c" still reference the same
    list.

    Now, in that last, it may look like we are changing an immutable
    integer. We are not. In all those lists where I have a simple integer:
    [5, 6]
    the actual list contents are:
    [reference to 5, reference to 6]
    so that third line is not changing the 6 to a 4, it changing the
    "reference to 6" into a "reference to 4"

    Names in Python are always (not just in function parameters)
    references to objects. An assignment to a name itself always changes the
    reference from the old object to a new object. Assignments to qualified
    names (l3[1], l1.append(), etc.) are changing the references INSIDE the
    object the name references (as long as that object is a mutable object),
    but do not change the reference of the name.


    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Home Page: <http://www.dm.net/~wulfraed/> <
    > Overflow Page: <http://wlfraed.home.netcom.com/> <
    Dennis Lee Bieber, Aug 9, 2005
    #10
  11. Re: Passing arguments to function - (The fundamentals are confusingme)

    Dennis Lee Bieber wrote:
    > In a more simplistic view, I'd reverse the phrasing... The name
    > "x" is assigned to the object "y" (implying it is no longer attached to
    > whatever used to have the name)


    No, because that'd imply that the object 'y' somehow keeps track of the
    names assigned to it, which is only true from a refcount perspective --
    and only on some Python implementations at that. The object is the
    property of the name, not vice versa.
    Christopher Subich, Aug 9, 2005
    #11
  12. Re: Passing arguments to function - (The fundamentals are confusingme)

    infidel wrote:
    >>in Python equality rebinds the name

    >
    >
    > Assignment (=) rebinds the name. Equality (==) is something else
    > entirely.


    Good catch. I was thinking of it as the "equals" operator.
    Christopher Subich, Aug 9, 2005
    #12
  13. Re: Passing arguments to function - (The fundamentals are confusingme)

    Rocco Moretti wrote:
    > Variables in Python are names. They aren't the cubbyholes into which you
    > put values, they are sticky notes on the front of the cubby hole.


    +1 MOTW (Metaphor of the Week)
    Christopher Subich, Aug 9, 2005
    #13
  14. Re: Passing arguments to function - (The fundamentals are confusingme)

    Dennis Lee Bieber wrote:
    > On Tue, 09 Aug 2005 10:39:29 -0500, Rocco Moretti
    > <> declaimed the following in comp.lang.python:
    >
    >
    >>Change it to "the object referenced by y is assigned to the name of x",
    >>and you're closer to the truth.

    >
    > In a more simplistic view, I'd reverse the phrasing... The name
    > "x" is assigned to the object "y" (implying it is no longer attached to
    > whatever used to have the name)


    I guess I was too subtle - my point was lost. The key thing is not to
    think of "the object 'y'" but to think of "the object referenced by
    (named) 'y'" There is a distinction between the object (object) and the
    name (variable), which is essential to eliminating the OP's conundrum.
    Rocco Moretti, Aug 9, 2005
    #14
  15. Re: Passing arguments to function - (The fundamentals are confusingme)

    Christopher Subich wrote:
    > Rocco Moretti wrote:
    >
    >> Variables in Python are names. They aren't the cubbyholes into which
    >> you put values, they are sticky notes on the front of the cubby hole.

    >
    >
    > +1 MOTW (Metaphor of the Week)


    Thanks, but please note it's not really mine - I've seen it somewhere
    else before. I thought it was from the website I linked earlier[1], but
    now I'm a little embarrased to find out that isn't, and I have no clue
    where it's from.

    [1] http://starship.python.net/crew/mwh/hacks/objectthink.html
    Rocco Moretti, Aug 9, 2005
    #15
  16. Re: Passing arguments to function - (The fundamentals are confusingme)

    Thanks everyone. I understand now. Everything is a reference, all
    that matters is whether I can go inside the "cubbyhole" and change
    something. Immutables don't allow this.

    So what if I do want to share a boolean variable like so:
    <code>
    sharedbool=True
    class cls1:pass
    cl=cls1()
    cl.sharedbool1=sharedbool

    sharedbool=False

    >>cl.sharedbool1

    True #but I wanted false!
    </code>

    My guess having read this threat would be to make a simple wrapper
    class for a boolean so I'm changing something inside the object
    instead of reassigning it?
    <code>
    class bigbool:
    /t def __init__(self,tf):
    /t/t self.val=tf
    /t def setval(self,tf):
    /t/t self.val=tf
    </code>
    Is there an easier way?


    -Greg

    On 8/9/05, Rocco Moretti <> wrote:
    > Christopher Subich wrote:
    > > Rocco Moretti wrote:
    > >
    > >> Variables in Python are names. They aren't the cubbyholes into which
    > >> you put values, they are sticky notes on the front of the cubby hole.

    > >
    > >
    > > +1 MOTW (Metaphor of the Week)

    >
    > Thanks, but please note it's not really mine - I've seen it somewhere
    > else before. I thought it was from the website I linked earlier[1], but
    > now I'm a little embarrased to find out that isn't, and I have no clue
    > where it's from.
    >
    > [1] http://starship.python.net/crew/mwh/hacks/objectthink.html
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >



    --
    Gregory Piñero
    Chief Innovation Officer
    Blended Technologies
    (www.blendedtechnologies.com)
    =?ISO-8859-1?Q?Gregory_Pi=F1ero?=, Aug 9, 2005
    #16
  17. Re: Passing arguments to function - (The fundamentals are confusingme)

    Gregory Piñero wrote:
    > So what if I do want to share a boolean variable like so:


    Well, the easiest way is to wrap it in a list:

    mybool = [True]
    mybool[0] = False
    mybool[0] = True

    and so on.

    Alternately, what is this boolean attached to that's so significant?
    Sharing an arbitrary boolean, without any context, is rather strange --
    perhaps it would be best to include both the boolean and associated
    context in a single, larger object.

    Also, remember that Python functions can return more than one value,
    through implicit tuple packing and unpacking. This greatly reduces the
    need for C-like result = function(&other_result) - isms.

    def myfunc():
    return 1,2,3
    (a,b,c) = myfunc()
    a == 1
    b == 2
    c == 3
    Christopher Subich, Aug 9, 2005
    #17
  18. =?ISO-8859-1?Q?Gregory_Pi=F1ero?=

    Terry Reedy Guest

    Re: Passing arguments to function - (The fundamentals are confusingme)

    "Christopher Subich" <> wrote in
    message news:0S5Ke.5236$...
    > Dennis Lee Bieber wrote:
    >> In a more simplistic view, I'd reverse the phrasing... The name
    >> "x" is assigned to the object "y" (implying it is no longer attached to
    >> whatever used to have the name)


    I agree that this is the more useful way to see it. I intentionally said
    'useful' rather than 'correct' since I consider the former to be the way to
    judge viewpoints. And I base the usefullness view on an informal (and yes,
    unscientific) mental tabulation of newbie confusions posted to c.l.p over
    several years. But better data could revise my judgment..

    > No, because that'd imply that the object 'y' somehow keeps track of the
    > names assigned to it,


    I disagree with your implication and see it the other way. To me, 'the
    object is bound to a name' implies that the object can only be bound to
    one name while the name could have many objects bound to it, which is the
    opposite of the case.

    Analogy: in an elementary school, students are assigned to (bound to) a
    room. The name=>room binding is recorded in a list (the 'namespace',
    alphabetical for lookup of names) in the principal's office. The rooms do
    not have to have a list of the students assigned to them, even though one
    could be derived from the master list, as one could

    Put another way: 'the name is bound' implies pretty clearly that the name
    is acted up, and it is that acting upon that makes the object a (new)
    property of the name. Nothing need be done to the object itself. This is
    even clearer if 'bound' is expanded to 'associated with object-fetch
    information'. So 'x = y' means "associated name 'x' with the object-fetch
    information that name 'y' is currently associated with."

    >The object is the property of the name, not vice versa.


    I agree, and see the binding of the name (to the object, as explained
    above) as that which sets the property.

    Terry J. Reedy
    Terry Reedy, Aug 10, 2005
    #18
  19. =?ISO-8859-1?Q?Gregory_Pi=F1ero?=

    Terry Reedy Guest

    Re: Passing arguments to function - (The fundamentals are confusingme)

    "Gregory Piñero" <> wrote in message
    news:...
    >Ahh, so it's a mutable thing. That makes sense that I can't change a
    >mutable object and thus can't affect it outside of the function.


    You of course meant immutable, but this is still confused. It is a
    name-binding versus object mutation thing.

    > Does that mean Python functions aren't always byref,
    > but are sometimes byval for nonmutables?


    No, neither. Python functions calls are always by name binding. See my
    first response. You are only about the 1000th or maybe 10000th person
    confused by trying to apply inapplicable concepts to Python.

    Terry J. Reedy
    Terry Reedy, Aug 10, 2005
    #19
  20. On Tue, 09 Aug 2005 13:39:08 -0500, Rocco Moretti
    <> declaimed the following in comp.lang.python:

    > Christopher Subich wrote:
    > > Rocco Moretti wrote:
    > >
    > >> Variables in Python are names. They aren't the cubbyholes into which
    > >> you put values, they are sticky notes on the front of the cubby hole.

    > >
    > >
    > > +1 MOTW (Metaphor of the Week)

    >
    > Thanks, but please note it's not really mine - I've seen it somewhere
    > else before. I thought it was from the website I linked earlier[1], but
    > now I'm a little embarrased to find out that isn't, and I have no clue
    > where it's from.


    I may not have been the first, but I've been using the simile of
    Post-It Notes for Python for years now (since I typically run
    X-NoArchive=Yes, Google won't have me -- though now that I've upgraded
    to Agent 3.0 and nothing works the same, who knows)

    The one time I didn't use that comparison, I got dinged (see
    above where I discussed reversing the phrasing, so names "get assigned
    to" object; to me that is putting the note ON the object, not that the
    object suddenly knows about another name).
    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Home Page: <http://www.dm.net/~wulfraed/> <
    > Overflow Page: <http://wlfraed.home.netcom.com/> <
    Dennis Lee Bieber, Aug 10, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Doug

    Python / glade fundamentals

    Doug, Mar 16, 2006, in forum: Python
    Replies:
    6
    Views:
    654
    Ido Yehieli
    Mar 20, 2006
  2. bart
    Replies:
    0
    Views:
    448
  3. gdv
    Replies:
    4
    Views:
    626
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=
    Oct 14, 2007
  4. XyZed
    Replies:
    21
    Views:
    769
    dorayme
    Jan 17, 2008
  5. bart
    Replies:
    0
    Views:
    481
Loading...

Share This Page