Access `self` of an object through the parameters
Not recommended, but instance_eval
would somehow work:
[1, 2, 3, 4].instance_eval { at(rand(size)) }
And you can also break
out of tap
:
[1, 2, 3, 4].tap { |a| break a.at(rand(a.size)) }
There's an open feature request to add a method that yields self
and returns the block's result. If that makes it into Ruby, you could write:
[1, 2, 3, 4].insert_method_name_here { |a| a.at(rand(a.size)) }
The proper way to access the self property of a class
I wouldn't go down that rabbit hole. Even if assigning back to self
would have worked, it would be a nightmare to debug and maintain.
I'd use classmethods to allow creating one type from another. Assigning back is not more clumsy than secretly changing types under the hood.
classmethods are the idiomatic way to create objects of a certain type from objects of another type in Python. It is essentially a "workaround" for the fact that Python does not support constructor overloading (or any method overloading, for that matter).
Explicit is better than implicit.
class newString(str):
@classmethod
def from_newInt(cls, new_int_obj):
return cls(str(new_int_obj))
class newInt(int):
@classmethod
def from_newString(cls, new_string_obj):
return cls(int(new_string_obj))
s = newString('1')
i = newInt(1)
print(type(newString.from_newInt(i)))
print(type(newInt.from_newString(s)))
# <class '__main__.newString'>
# <class '__main__.newInt'>
Accessing self in a function attribute
You can use descriptors here:
class deco(object):
def __init__(self, func):
self.func = func
self.parent_obj = None
def __get__(self, obj, type=None):
self.parent_obj = obj
return self
def __call__(self, *args, **kwargs):
return self.func(self.parent_obj, *args, **kwargs)
def string(self, *args, **kwargs):
return str(self(*args, **kwargs))
class Test(object):
def __init__(self, value):
self._value = value
@deco
def plus(self, n):
return self._value + n
so that:
>>> test = Test(3)
>>> test.plus(1)
4
>>> test.plus.string(1)
'4'
This warrants an explanation. deco
is a decorator, but it is also a descriptor. A descriptor is an object that defines alternative behavior that is to be invoked when the object is looked up as an attribute of its parent. Interestingly, bounds methods are themselves implemented using the descriptor protocol
That's a mouthful. Let's look at what happens when we run the example code. First, when we define the plus
method, we apply the deco
decorator. Now normally we see functions as decorators, and the return value of the function is the decorated result. Here we are using a class as a decorator. As a result, Test.plus
isn't a function, but rather an instance of the deco
type. This instance contains a reference to the plus
function that we wish to wrap.
The deco
class has a __call__
method that allows instances of it to act like functions. This implementation simply passes the arguments given to the plus
function it has a reference to. Note that the first argument will be the reference to the Test
instance.
The tricky part comes in implementing test.plus.string(1)
. To do this, we need a reference to the test
instance of which the plus
instance is an attribute. To accomplish this, we use the descriptor protocol. That is, we define a __get__
method which will be invoked whenever the deco
instance is accessed as an attribute of some parent class instance. When this happens, it stores the parent object inside itself. Then we can simply implement plus.string
as a method on the deco
class, and use the reference to the parent object stored within the deco
instance to get at the test
instance to which plus
belongs.
This is a lot of magic, so here's a disclaimer: Though this looks cool, it's probably not a great idea to implement something like this.
Access 'self' within an object when other arguments are also commited (perl)
Use of uninitiated value $person in concatenation (.) or String at Line 22.
When calling test2
method you've forgot $person
argument, ie.
$i->test2();
should be
$i->test2("Someone");
What is the purpose of the `self` parameter? Why is it needed?
The reason you need to use self.
is because Python does not use special syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically, but not received automatically: the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions, and leaves the actual name to use up to you (although self
is the convention, and people will generally frown at you when you use something else.) self
is not special to the code, it's just another object.
Python could have done something else to distinguish normal names from attributes -- special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different -- but it didn't. Python's all for making things explicit, making it obvious what's what, and although it doesn't do it entirely everywhere, it does do it for instance attributes. That's why assigning to an instance attribute needs to know what instance to assign to, and that's why it needs self.
.
where does the 'self' object comes from in the method __init__?
__init__
behaves like any other normal function in a class. It gets called by the interpreter at a special time if it is defined, but there is nothing special about it. You can call it any time yourself, just like a regular method.
Here are some facts to help you see the picture:
Function objects are non-data descriptors in python. That means that function objects have a __get__
method, but not __set__
. And if course they have a __call__
method to actually run the function.
When you put a def
statement in a class body, it creates a regular function, just like it would elsewhere. You can see this by looking at type(Test.__init__)
. To call Test.__init__
, you would have to manually pass in a self
parameter.
The magic happens when you call __init__
on an instance of Test
. For example:
a = Test()
a.__init__()
This code actually calls __init__
twice (which we'll get into momentarily). The explicit second call does not pass in a parameter to the method. That's because a.__init__
has special meaning when the name __init__
is present in the class but not the instance. If __init__
is a descriptor, the interpreter will not return it directly, but rather will call __get__
on it and return the result. This is called binding.
a.__init__()
is roughly equivalent to type(a).__init__.__get__(a, None)()
. The call .__get__(a, None)
returns a callable object that is a bound method. It is like a special type of partial function, in which the first positional parameter is set to a
. You can see this by checking type(a.__init__)
.
The self
parameter is passed to methods as the first positional parameter. As such, it does not have to be called self
. The name is just a convention. def __init__(this):
or def __init__(x)
would work just as well.
Finally, let's discuss how a = Test()
ends up calling __init__
. Class objects are callable in python. They have a class themselves, called a metaclass (usually just type
), which actually defines a __call__
method. When you do Test()
, you are literally calling the class.
By default, the __call__
method of a class looks something (very roughly approximately) like this:
def __call__(cls, *args, **kwargs):
self = cls.__new__(cls, *args, **kwargs)
if isinstance(self, cls):
type(self).__init__(self, *args, **kwargs)
So a new instance is only created by __new__
, not __init__
. The latter is an initializer, not a constructor or allocator. In fact, as I mentioned before, you can call __init__
as often as you like on most classes. Notable exceptions include immutable built-in classes like tuple
and int
.
As an initializer, __init__
obviously needs access to the object it is initializing. Your example does nothing with self
, but it is pretty standard to set instance attributes and do something things to prep the object. For cases like yours, an explicit __init__
is not necessary at all, since a missing function will be found in the base class hierarchy.
Can I access class variables using self?
Assigning remote
to self
in __init__
means that instance.remote
is found first when you access it through self
(granted no descriptors are around). To get both options, access either from self
or from type(self)
, that is, either from the instance or the class:
def print_remote(self):
print(type(self).remote) # class remote
print(self.remote) # instance remote
type(self).remote
is essentially equivalent to self.__class__.remote
but, in general, you should avoid grabbing dunder names (__*__
) when there's a built in that does it for you (type
in this case)
These live in different dictionaries and are different variables. self.remote
lives in the instance dict while class.remote
in the class dict.
>>> Foo().__dict__['remote']
True
>>> Foo.__dict__['remote']
False
When you access through cls
with a classmethod
(or type(self)
in a normal method) you'll get the class one, when you access through self
you get the instance one.
How can a JavaScript object refer to values in itself?
Maybe you can think about removing the attribute to a function. I mean something like this:
var obj = { key1: "it ", key2: function() { return this.key1 + " works!"; }};
alert(obj.key2());
How have access to both cls and self in a method
As a very brief review, self
refers to a current instance of the class while cls
variables are attached to the class itelf i.e., shared among every instance. Here are some references to help with this, and how I got to your solution:
- https://stackoverflow.com/a/25577642/5557662
- Python datamodel docs
I modified your sample code to illustrate the difference and included a solution:
class MyClass:
__var2 = 'var2'
var3 = 'var3'
def __init__(self):
self.__var1 = 'var1'
def normal_method(self):
print(self.__var1)
@classmethod
def class_method(cls):
print(cls.__var2)
def my_method(self):
print(self.__var1)
print(self.__var2)
print(self.__class__.__var2)
if __name__ == '__main__':
print(MyClass.__dict__['var3'])
clzz = MyClass()
clzz.my_method()
__var2
and var3
are variables saved to the class. You can access any class variable without an instance via __dict__
which represents the name space.
Since class variables become a part of every instance, you can just call self
to access them. Alternatively, you can explicitly call self.__class__.__var2
to make it clear where the intended variable is actually stored.
Passing 'self' parameter during methods decorating in Python
It's not working with you current design because of how classes work in Python.
When a class is instantiated, the functions on it get bound to the instance -
they become bound methods, so that self
is automatically passed.
You can see it happen:
class A:
def method1(self):
pass
>>> A.method1
<function A.method1 at 0x7f303298ef28>
>>> a_instance = A()
>>> a_instance.method1
<bound method A.method1 of <__main__.A object at 0x7f303a36c518>>
When A is instantiated, method1
is magically transformed from afunction
into a bound method
.
Your decorator replaces method1
- instead of a real function,
it is now an instance of _PrintingArguments
. The magic
that turns functions into bound methods is not applied to random
objects, even if they define __call__
so that they behave like a function. (But that magic can be applied, if your class implements the Descriptor protocol, see ShadowRanger's answer!).
class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
class A:
@Decorator
def method1(self):
pass
>>> A.method1
<__main__.Decorator object at 0x7f303a36cbe0>
>>> a_instance = A()
>>> a_instance.method1
<__main__.Decorator object at 0x7f303a36cbe0>
There is no magic. method1
on the instance of A is not a bound method,
it's just a random object with a __call__
method, which will not haveself
passed automatically.
If you want to decorate methods you have to replace the decorated function
with another real function, an arbitrary object with __call__
will not do.
You could adapt your current code to return a real function:
import functools
class _PrintingArguments:
def __init__(self, default_comment, comment_variable):
self.comment_variable = comment_variable
self.default_comment = default_comment
def __call__(self, function):
@functools.wraps(function)
def decorated(*args, **kwargs):
comment = kwargs.pop(self.comment_variable, self.default_comment)
params_str = [repr(arg) for arg in args] + ["{}={}".format(k, repr(v)) for k, v in kwargs.items()]
function_call_log = "{}({})".format(function.__name__, ", ".join(params_str))
print("Function execution - '{}'\n\t{}".format(comment, function_call_log))
function_return = function(*args, **kwargs)
print("\tFunction executed\n")
return function_return
return decorated
def function_log(_function=None, default_comment="No comment.", comment_variable="comment"):
decorator = _PrintingArguments(
default_comment=default_comment,
comment_variable=comment_variable,
)
if _function is None:
return decorator
else:
return decorator(_function)
Related Topics
Getting a Rogue Iteration from My .Each Loop
Instance_Eval Does Not Work with Do/End Block, Only with {}-Blocks
Can't Dup Nilclass on Association Methods
Bootstrap Modal in Ruby on Rails Not Working
Shading Mask Algorithm for Radiation Calculations
How to Iterate Through This JSON Document Using Ruby
Run Ruby Script That Is Stored on Internet
Ruby Facebook Graph API Appsecret_Proof
How to Understand the #Dup and #Clone Operate on Objects Which Referencing Other Objects
Rails 404 Error for Stylesheet or JavaScript Files
Ruby File Reading Parallelisim
Inserting an Array into Every Nth Element of Another
Undefined Method 'Email' for Nil:Nilclass in Exibe the Mail of Table Father
Undefined Method Error When Creating Delayed_Job Workers with Script/Delay_Job
Import CSV in Batches of Lines in Rails
How to Get Repeated Elements from Ruby Array