How to avoid using 'self' so much [duplicate] - python

This question already has answers here:
How to avoid explicit 'self' in Python?
(11 answers)
python self-less
(3 answers)
Closed 9 years ago.
I am writing a program to simulate a small physical system and have become more and more annoyed as I write things like this:
K = 0.5 * self.m * self.v**2
In the case above, the equation is short and pretty understandable, but I have situations in which there is so much self that the whole thing ends up looking like a mess. I am aware that python always requires self to refer to class members, but is there a way to to make the code not look like a mosaic of self's?
EDIT: I usually do things such as:
var = self.var
and keep on using var instead of self.var. Later I do:
self.var = var
but this seems really stupid. What would be the pythonic way to solve this problem?

For messy parts I'd use Python modules and "module-level variables" instead of classes.

If all you want to do is save some keystrokes, you can always rename self to s:
class MyClass(object):
def kinetic_energy(s): # use s instead of self for brevity
return 0.5 * s.m * s.v**2
This saves you 3 characters per use of self. This goes against the standard convention, but nothing is stopping you from doing this. I would advice against doing this in general code, but it might be justified if it makes some very long formulas more readable. Do mention the unusual choice in a comment, in case anyone else has to read your code when you are long gone.

I guess it's possible to use some black magic in Python and come up with a context manager, which will take an object and put all its attribute in the context's locals(), and assign it back to object in the __exit__ function.
Found this https://code.google.com/p/ouspg/wiki/AnonymousBlocksInPython which may help.

Related

how to make new flow controls in python? [duplicate]

This question already has answers here:
Can you add new statements to Python's syntax?
(13 answers)
Closed 2 months ago.
Not sure how to explain, I mean statemtents like:
for i in l:
if a==b:
def x():
lambda x:
class spam:
while True:
basically those control statements that end with :
can I create novel ones? (like in snakemake that has a long list of new control statements)
I tried reading documentation, but could not find anything useful.
I just want to make some tools to help develop rules for snakemake.
I am currently using this:
class SM(object):
def __init__(self,**xargs):
self.items = xargs
def __getattribute__(self,attr):
return object.__getattribute__(self, "items")[attr]
input = SM(genome="Genome/genome.fa",
table="rmats/binding_strength.maxent.CLIP.csv")
table = pd.read_csv(input.table,index_col=0)
In that example I can use the class SM to emulate all the input, output, wildcard... then I can just move the code into its rule in the Snakefile without needing to manually edit all the inputs/wildcards/outputs...
However, I will still need to write the "input:".
Is there a way I could make:
input:
table="table.csv"
do
input=SM(table:"table.csv")
#or input=SM(**xargs)
Sorry, but no can do...You would have to modify the language implementation itself (the interpreter actually). When you are programming you are bound by the syntax of the language, you cannot modify the syntax "on the fly". It's not the same as e.g. defining functions, classes and whatnot.
Take a look at these:
Can you add new statements to Python's syntax?
How to make custom reserved keywords in python3
Here's the most comprehensive answer to this kind of questions imho:
https://stackoverflow.com/a/9108164/15923186

Bracket not showing as closed in Python 3

I'm just starting to learn Python 3.9 as my first language. I have been fighting with this error for a while now, and I can't figure out what the issue is.
Here's what I'm working on:
def eval_express(eqstring[0], eqstring[1], eqstring[2]):
eqstring[0], eqstring[2] = float(eqstring[0]), float(eqstring[2])
return opdict[eqstring[1]](eqstring[0], eqstring[2])
I'm receiving an error that the "(" after eval_express is not closed, but as far as I can tell it is. At first, I thought it was just a glitch, but despite numerous attempts to rewrite it, increase/decrease the number of arguments, etc. it persisted. The error cropped up after I modified the arguments from variables to list items, but I don't see why that would affect it. Can anyone provide some clarification on what the program's getting hung up on?
Thank you for your help!
You are using square brackets inside the function parameters, which is not valid. Valid code would be:
def eval_express(eqstring0, eqstring1, eqstring2):
eqstring0, eqstring2 = float(eqstring0), float(eqstring2)
return opdict[eqstring1](eqstring0, eqstring2)
although you should probably use more descriptive parameter names.
You can't use parameter[] notation when entering a parameter to a function. Instead just use parameter, or you will have to do something like.
def eval_express(eqstring):
eqstring[0], eqstring[2] = float(eqstring[0]), float(eqstring[2])
return opdict[eqstring[1]](eqstring[0], eqstring[2])
Now you have to pass an array as the function parameter.

Checking argument values at runtime in python [duplicate]

This question already has answers here:
Obtaining closures at runtime [duplicate]
(1 answer)
How to open a closure in python?
(5 answers)
Closed 2 years ago.
I would like to know if there is any method to check whether two functions have the same arguments at runtime in python 3.
Basically, I have this function (func) that takes two arguments and perform some sort of computation. I want to check whether or not a and b have the same arguments' values at runtime
a = func(2, 3)
b = func(2, 3)
a.argsvalue == b.argsvalue
It is not feasible to run the code before and check the results because I am implementing a lazy framework. My main goal is to be able to understand what are the arguments of the function because there is one variable argument that I do not care but there is one static that is created before running the function.
##EDIT
I actually solved this problem using the inspect module (getclosure) for those who are interested. Thank you so much for the comments it helped me to familiarize myself with the terminology. I was actually looking for the closure, which I assigned dynamically.
when you do this - a.argsvalue == b.argsvalue you try to access a member of the value returned from the function.
so, if your "func" would return an object having the args you called it with (which sound like a weird thing to do) you would be able to access it.
anyway, if you need these values, just store them before sending them to the function, and then you can do whatever you want with them.

In python, when does pass by reference occur? [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 2 years ago.
I have a code as below,
attractions = [[] for i in range(5)]
def add_attraction(attraction):
attractions_for_destination = attractions[2]
attractions_for_destination.append(attraction)
return
pass by reference occurs in 3rd line "attractions_for_destination = attractions[2]". The general idea of pass by reference that I have is that it happens between actual parameter and formal parameter. But the above line is a simple assignment code. Can pass by reference happen in a simple assignment code?
If so, if I write
attractions_for_destination = attractions[2] + ": best attraction site"
will altering the value force the newly made variable to use a new memory space?
Saying pass by reference or pass by value isn't really applicable to python. For example consider Java. Everything in Java is pass by value, everything. However the value of an object is the reference to the object. So it is, in a way, pass by reference since mutating the object will be reflected to the calling context. Calling it "pass by value" is a bit confusing since for people used to C-family (where this distinction is more straightforward) assume that pass by value means you won't modify the underlying argument passed.
So saying Java is "pass by value" is true but possibly confusing. It is a more relevant statement at much lower levels of the language (like when talking about how the compiler handles passing arguments but not at the level of application programmer).
Python is similar. The confusion about the Java example actually lead Python to not say if it is pass by value/reference. http://stupidpythonideas.blogspot.com/2013/11/does-python-pass-by-value-or-by.html
So for programming, it is save to assume that any object is "passed by reference" (technically no but essentially yes). It is more complicated than that but that link explains it in more depth.

Python 3: Can we avoid repeating an instance name when calling several of its methods?

I now (or so I have read) that it is not possible in Python 2.x, and can't find it for Python 3 either, but maybe I don't know how to search for it...
It easier to explain it with a simple Python example:
for i in range(11):
one_turtle.penup()
one_turtle.forward(50)
one_turtle.down()
one_turtle.forward(8)
one_turtle.up()
one_turtle.forward(8)
one_turtle.stamp()
one_turtle.forward(-66)
one_turtle.left(360/12)
I'd like to avoid repeating "one_turtle" the same way you can do in VBA, which it would result in something similar to this:
For i = 1 To 11
With one_turtle.penup()
.forward(50)
.down()
.forward(8)
.up()
.forward(8)
.stamp()
.forward(-66)
.left(360/12)
The code resulting from the With keyword is much clearer and easy to write and read (it'll need an End With and a Next lines but I wanted to focus the discussion). One of the main reasons I have decided to learn Python is because it is said to be very neat and "zen-like" to program. Is it really not possible to do this?
In your definition of all these member-methods, simply return self.
eg. Change definition of penup() like this:
def penup(self):
# Your logic
return self
The ideal solution is I think already posted, returning self is simply the cleanest way. However if you're not able to edit the turtle object or whatever, you can create an alias:
forward = one_turtle.forward
... some code ...
forward()
Now the function forward just applies forward to one_turtle, simple example
s = "abc"
x = s.upper
print(x()) # prints "ABC"

Categories