Python objects passing objects

Python — Passing object value instead of reference

In Python, as I understand it, variables are really references to objects in the given namespace. So in the following example, it is unsurprising that when noise changes in the global namespace, the value returned by cat.noise changes, as the reference in the setattr line is using the reference of noise , not its underlying value.

class Cat(object): pass noise = "meow" setattr(Cat, "noise", property(lambda self: noise)) cat = Cat() cat.noise # Outputs "meow" noise = "purrrrr" cat.noise # Outputs "purrrrr" 

That being said, is there a way to pass the value of noise when calling setattr as above? I figured that I could isolate the namespace by using a function, and that did work:

class Cat(object): pass noise = "meow" def setproperties(cls, k, v): setattr(cls, k, property(lambda self: v)) setproperties(Cat, "noise", noise) cat = Cat() cat.noise # Outputs "meow" noise = "purrrrr" cat.noise # Still outputs "meow" 

Is it possible to do so without passing the object through a function (without using eval or the like)? And as a secondary question, is my reasoning about what goes on under the hood correct?

EDIT

As per the request for a less contrived example in the comments, consider the following. Imagine I am trying to dynamically set attributes in Cat , based on the values of its friend Dog :

class Dog(object): noise = 'woof' adorable = True class Cat(object): friend = Dog friend_attrs = filter(lambda attr: not attr.startswith('__'), Dog.__dict__) for attr in friend_attrs: setattr(Cat, "friend_" + attr, property(lambda self: getattr(self.friend, attr))) cat = Cat() cat.friend_noise # Outputs True cat.friend_adorable # Outputs True 

Источник

Читайте также:  Html открыть новое окно по кнопке

Passing Objects in Python

Passing Objects in Python

Passing Objects in Python

In Python, objects and data can be passed in several ways:

Pass by reference: When an object is passed as an argument to a function, a reference to the object is passed, not a copy of the object. Any changes made to the object within the function will be reflected outside the function as well.

def modify_list(my_list): my_list.append(4) print("Inside function:", my_list) my_list = [1, 2, 3] print("Before function call:", my_list) modify_list(my_list) print("After function call:", my_list) 

The output of this code will be:

Before function call: [1, 2, 3] Inside function: [1, 2, 3, 4] After function call: [1, 2, 3, 4] 

As you can see, the append() method is called inside the function, which adds the number 4 to the list. Even though the list is passed as an argument to the function, the change made inside the function is reflected outside the function as well, because the list is passed by reference. Let’s now examine another way we pass objects.

Pass by value: In python, all variables are references, whether it is a list, a dictionary, a string, a boolean or even an integer. Python does not have a direct pass by value mechanism, but it is possible to achieve pass by value behavior by passing a copy of the object to the function. The copy module can be used to create a shallow copy of the object, and the deepcopy module can be used to create a deep copy of the object. Here is an example of passing a list as an argument to a function:

def modify_list(my_list): my_list[0] = 'Changed' print("Inside function:", my_list) my_list = ['original', 'values'] print("Before function call:", my_list) modify_list(my_list) print("After function call:", my_list) 

In this example, the modify_list function takes a list as an argument and modifies the first element of the list. Then, it prints the list both before and after the function call.

The output of this code will be:

Before function call: ['original', 'values'] Inside function: ['Changed', 'values'] After function call: ['Changed', 'values'] 

As you can see, the first element of the list is changed inside the function, and this change is reflected outside the function as well because the list is passed by reference.

Pass by object: Python uses a concept called «call-by-object», which is similar to call-by-reference. When an object is passed as an argument to a function, a reference to the object is passed, and any changes made to the object within the function will be reflected outside the function. However, if the object is immutable, any changes made to the object will result in a new object, and the original object will remain unchanged.

Here’s an example of how we can create a new reference to an object within a function and make changes to it, without affecting the original object:

def modify_list(my_list): my_list = my_list + [4] print("Inside function:", my_list) my_list = [1, 2, 3] print("Before function call:", my_list) modify_list(my_list) print("After function call:", my_list) 

In this example, the modify_list function takes a list as an argument, but it creates a new reference to the list and assigns it to the variable my_list . Then, it modifies the new list by appending the number 4 to it. Finally, it prints the original list both before and after the function call.

The output of this code will be:

Before function call: [1, 2, 3] Inside function: [1, 2, 3, 4] After function call: [1, 2, 3] 

As you can see, the original list is not modified, because the function created a new reference to the list and made changes to that reference.

This example is not exactly pass by object, but it shows how we can make changes to a new reference of an object and not affect the original one.

Default arguments: When a default value is specified for an argument in a function definition, this value is used as the default value for that argument when the function is called. In Python, default arguments allow you to specify default values for function parameters. If a value for a parameter is not provided when the function is called, the default value will be used. Here is an example of a function with default arguments:

def greet(name, greeting = "Hello"): print(greeting + ", " + name + "!") greet("Akiva") # "Hello, Akiva!" greet("Sarah", "Shalom") # "Shalom, Sarah!" 

In this example, the function greet takes two parameters: name and greeting . The greeting parameter has a default value of «Hello». When the function is called with only one argument, the default value is used for the greeting. When the function is called with two arguments, the second argument overrides the default value.

It’s important to note that Default arguments are evaluated only once at the time of function definition. It means that if the default argument is a mutable object, like a list or a dictionary, and you modify it inside the function, the change will be reflected in the next call as well.

def add_item(item, items=[]): items.append(item) return items print(add_item(1)) # [1] print(add_item(2)) # [1, 2] 

In this example, since the default argument is a list, when the list is modified inside the function, the change will be reflected in the next call as well.

To avoid this, you can use None as the default value and create a new object inside the function if the value is None.

def add_item(item, items=None): if items is None: items = [] items.append(item) return items print(add_item(1)) # [1] print(add_item(2)) # [2] 

In this way, a new object is created every time the function is called, avoiding unexpected behavior.

Variable-length arguments: Python supports variable-length arguments using the and * operators. The operator is used to pass a variable number of non-keyword arguments to a function, and the * operator is used to pass a variable number of keyword arguments to a function.

In Python, variable-length arguments allow a function to take an unspecified number of arguments.

There are two types of variable-length arguments in Python:

  • *args : used to pass a variable number of non-keyword arguments to a function.
  • **kwargs : used to pass a variable number of keyword arguments to a function.

Here’s an example of a function that uses *args to take a variable number of non-keyword arguments:

def print_args(*args): for arg in args: print(arg) print_args(1, 2, 3, "hello", "world") 

In this example, the function print_args takes a variable number of arguments and prints each one. When the function is called, any number of arguments can be passed, and they will be collected into a tuple called args .

Here’s an example of a function that uses **kwargs to take a variable number of keyword arguments:

def print_kwargs(**kwargs): for key, value in kwargs.items(): print(key + ": " + value) print_kwargs(name="John", age=25, city="New York") 

In this example, the function print_kwargs takes a variable number of keyword arguments and prints each one in the format «key: value». When the function is called, any number of keyword arguments can be passed, and they will be collected into a dictionary called kwargs .

It’s also possible to use both *args and **kwargs in the same function, you can use them in any order but typically *args is first and then **kwargs

def print_args_kwargs(*args, **kwargs): for arg in args: print("arg: ", arg) for key, value in kwargs.items(): print("kwarg: ", key, value) print_args_kwargs(1, 2, 3, name="John", age=25, city="New York") 

In this example, the function print_args_kwargs takes a variable number of arguments, both non-keyword and keyword, and prints each one. The non-keyword arguments are collected into a tuple called args and the keyword arguments are collected into a dictionary called kwargs .

It’s important to note that the use of * and ** is only a convention to indicate that the function accepts variable-length arguments, you can use any name you want.

This concludes our exploration of functions in python. How python functions works and some of their use cases. Go forth and practice, as well as share and subscribe.

Источник

Object Passing in Python

Austin Cepalia

In this lesson, you’ll learn that Python doesn’t pass objects by value or reference. Python passes objects by assignment instead. In the examples, you’ll see how this differs when the object is mutable or immutable.

At ~4:23 in Object Passing in Python you inadvertently described the list type as immutable. It’s fairly clear from the context that you meant to say mutable, but might be worth an edit .

When describing pass-by-assignment, it would have been very helpful to show what that means in much the same way as you showed how assigning names to objects works.

Given this function definition and call:

def foo(v): v += 1 w = 1 foo(w) print(w) 

The pass-by-assignment behavior makes this roughly equivalent to

w = 1 v = w # pass by assignment -- now v is just another name for w v += 1 # now v is replaced by a new object containing 2 del(v) # after we return from v, the name v no longer exists print(w) # w still points at the same object containing 1 

Tadej P on Oct. 7, 2020

I think the explanation at 1:33 gives the wrong impression that objects are passed differently based on their mutability.

The difference is that objects of mutable types have facilities to change their internal state, while immutable ones don’t.

So the only way to change the value of a name containing an immutable type is by reassignment, at which point that name refers to a different object.

But because, at function call, the arguments get a new name object (a copy) that points to their PyObject, the original name outside the scope is not affected.

To expand on carl’s example:

>>> def foo(v): . print(id(v)) . v = v+1 . print(id(v)) . >>> w = 1000 >>> id(w) 140247376306096 # w points to PyObject containing 1000 >>> foo(w) 140247376306096 # v points to original PyObject containing 1000 140247376306000 # v now points to different PyObject containing 1001 >>> id(w) 140247376306096 # w is unaffected, still points to original pyObject containing 1000 

Hi, first thank you for this awesome tutorial.

In this video I got a bit confused, at 04:19 you said “The list type is mutable, meaning that this should mimic pass-by-value behavior.” But later at 05:10 talking about the list you said “I will run this and you see, it appears we’ve lost our pass-by-reference behavior.” I think since the list is mutable it should mimic the pass-by-reference behavior. Could you please correct me if I’m wrong please?

Bartosz Zaczyński RP Team on Jan. 24, 2021

@raulfz To make things easier, you can think of this as if everything in Python was passed by value. In other words, every argument a function receives is copied inside of it.

The different behavior will depend on the type of the actual parameter. When you pass something of a simple type, such as a string or number, it’ll copy the corresponding value that can be changed independently. On the other hand, passing an object to a function will copy its reference. You’ll have one object but two or more ways to access it.

Источник

Оцените статью