Can someone tell me the function of this "self" - python-3.x

I use python to insert data into MySQL, in some tutorial, I must include "self" on my function,
Def haha(self, hihi):
Print(hihi)
I have no idea what does it mean..

This function takes instance of itself as an argument. It is done when declaring methods of a class because function needs to run the method from its own particular instance. Also self needed to access or update fields of particular instance of a class. For example:
class A:
b = 3
def f(self):
self.b = 5
So when you create object of type A and call method f from this object, only this object's b will become 5, but other objects of type A will have b equaling to 3. Also, when you call method, you do not pass instance of it as an argument, and can just start passing arguments starting after 'self'.

Related

Increment reference count of Python object

I have a static method that returns a new instance of it's class. The problem is that the instance is None in the code that called the method. I believe this is due to the fact the instance is created in a static method so it's reference count isn't incremented and it is released before the calling code can reference it. In C, I could call Py_INCREF() but I need to increment the reference count in Python code. What do I need to do?
class MyClass:
#staticmethod
def get(id: int) -> MyClass:
myobj = MyClass().configuredata()
return myobj
The issue here was not reference counting but rather that chaining of methods called a method that did not return self but instead returned None.

Reading class method definition - what is Callable?

I am relatively new to python, and I started to read the docs when using packages, but I'm having a hard time understanding some of it:
post_to_main_thread(self: open3d.cpu.pybind.visualization.gui.Application, arg0: open3d::visualization::gui::Window, arg1: Callable[[], None]) → None
the only thing here that I don't understand is the arg1 with that callable, and I can't find an explanation on it at the web.
Interesting question!
So post_to_main_thread() is a method that takes 3 arguments (inputs/variables) and returns None.
Because it's a method (a function associated with a class, not just a standalone function) the first argument, self, refers to the instance of the class that the function is part of.
The other two arguments are passed within the function parentheses, as expected with a standalone function. So a call might look like this:
instance_name = open3d.visualization.gui.Application(...)
instance_name.post_to_main_thread(arg1, arg2)
arg1 should be of type open3d::visualization::gui::Window. This is an instance of the class open3d.visualization.gui.Window().
arg2 should be of type Callable(). This describes a number of built-ins that you can find details about in the documentation. To quote:
The subscription syntax must always be used with exactly two values: the argument list and the return type. The argument list must be a list of types or an ellipsis; the return type must be a single type.
So in this case the type should be Callable[[], None], which means this should be a function that takes no input and returns None. Carrying on from our previous example, you'd pass this as an argument like so:
def my_callable:
print('Hello, World!')
return
instance_name.post_to_main_thread(arg1, my_callable)
Does that clear things up?

Why can a function that has no return statement modify an attribute in a user-defined class instance but not a built in class instance?

I understand that if I pass a variable as an argument to a function it can only change the value of that argument within its own scope, not the value of the variable at the global scope.
However, this doesn't seem to apply to passing user-defined class instances to a function, where I am able to modify that object in the global scope without a return statement in the function.
For example, in the code below I would have expected the function bar() to only modify the values within the scope of the function, and not change the 'my_class_object' instance of foo in the global scope. However, when I run bar() I find that the value of my_class_object.the_value changes from 0 to 1.
class foo():
def __init__(self,num):
self.the_value = num
def bar(a,b):
a.the_value +=1
b +=1
my_class_object = foo(0)
int_class_object = 0
bar(my_class_object,int_class_object)
print(my_class_object.the_value)
print(int_class_object)

defaultparameter in constructor magically becomes class variable [duplicate]

This question already has answers here:
"Least Astonishment" and the Mutable Default Argument
(33 answers)
Closed 3 years ago.
I'm having a problem understanding the following:
class Test():
def __init__(self, data = []):
self.data = data
a = Test()
b = Test()
a.data.append(1)
print(b.data) # prints [1]
class Test1():
def __init__(self, data):
self.data = data
a = Test1([])
b = Test1([])
a.data.append(1)
print(b.data) # prints []
class Test2():
def __init__(self, data = 1):
self.data = data
a = Test2()
b = Test2()
a.data = 2
print(b.data) # prints 1
It prints out [1]
I was expecting that the instance variable data of b would be an empty list, because it is a instance variable and not a class variable!
If I do the same thing without a default parameter and just pass an empty list to the parameter data it works. It also works with an int as a default parameter. I know lists are passed by reference, but that shouldn't be happening anyways.
How? why? Am I not seeing something here??
Your default argument for data is a mutable type! When python is creating the definition of your Test class, it only makes one instance of the default arguments. This means that every time you create a Test object, it's data property will be pointing to the same list. After you create both of your Test objects, both of their .data properties point to the exact same list in memory. If you change that list once, it will change it for all your Test classes. The list.append method modifies the list in place, hence why you see this behavior.
Notice in your Test1 case, you are creating two different empty lists and assigning them to the .data property. Since these are two separate lists, you can change either one however you please without affecting the other.
Python int's are not mutable, and even if they were, you are overwriting the .data property in your Test2 example so you get the expected behavior.
But sometimes, your function needs the default argument to be a list or some other mutable type! What you can do is assign the default value to None, and then check if the value is None inside the function. If it is, assign your property to your actual desired default value. Like this:
class Test:
def __init__(self, data = None):
self.data = [ ] if data is None else data
# Set self.data to an empty list if data is none, otherwise, set it to whatever data already is.
a = Test()
b = Test()
a.data.append(1)
print(f"a.data:{a.data}, b.data:{b.data}")
# >> a.data:[1], b.data:[]
Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.
https://docs.python-guide.org/writing/gotchas/

In python 3, how can I convert a function into an attribute

I have a simple function I can call like this:
bln=getColN(bl,n)
I'd like to call it like this:
bln=bl.getColN(n)
The details don't matter, because I'd like to know how to do this in general, but since someone will surely ask: bl is a list of lists (a 2D array) and bln is a 1D list consisting of the nth column of bl. Yes, I'm sure I can do it with a comprehension.
I'm using python 3.4 on a win7 system.
What you want is a step from Structured Programming to Object Oriented Programming in the syntax sense. The older code may be designed using OO principles (or OO approach can be simply natural). Firstly, the bl must be the object if the second form is to be used. An object is known also as an instance of a class. This way, you have to define your class.
Then, bl variable represents the object. In Python, it is the reference to the object. The object is created when you call the class name. The bl is the name of the object from outside the class definition. The name of the same object from inside the class definition is named self by convention.
To put it together, your function will be converted to member function of the class, and you should probably only rename the arr (the first argument in the old function) in the old function definition to self (to stick with the conventions). However, if bl (from outside of the function definition, or arr from inside of the function definition) was a list in the old code, it becomes an object reference. Think about the object as about a thin wrapper around your list. There are basically two ways to do that (composition and inheritance). Usually, the composition should be the prefered way when you do such conversion (unless you know what you are doing). It means that the object must store what was earlier the reference to the list. In the class definition, you will use self.arr (or more suitable name) as the member variable for storing the reference to the list. To do that, you have to implement a special method (a method is also named as a member function) named __init__ (the underscores are doubled):
class MyArray:
def __init__(self, arr):
self.arr = arr
In Python, self. prefix must be always used explicitly inside the class definition if you want to refere to member variables or member functions.
Now add your getColN:
def getColN(self, n):
... change your body slightly...
Say you had def getColN(arr, n) in your existing function. Then arr was the reference to the list of lists. But now, the first argument of the function must be the reference to the object (i.e. class instance), and the array is now named self.arr. This way, you should rename your earlier arr in the function body to the self.arr. Now you have:
class MyArray:
def __init__(self, arr):
self.arr = arr
def getColN(self, n):
... changed body...
You can use the new class definition to wrap the existing list of lists in the sense you pass the old structure to the constructed object:
x = MyArray(bl)
The x will be your new replacement for the old bl. The old bl is passed to the __init__ -- seen as arr from inside the class definition, and saved as self.arr.
And you can call:
bln = x.getColN(n)
I did use the x identifier to emphasize the difference only. When refactoring (rewriting the old code), you may want to prefer to keep the bl identifier -- to reuse it for a different purpose:
bl = MyArray(bl)
The bl as argument was the list of lists, but later it becomes the object reference.
When everything works, you can add implementation of other special methods, and you can easily use syntax for your object of your own class as if it was an array (here using x again to emphasize the idea):
bln = x[n]

Resources