Would you please look at code below,
def getCrewListAll(self):
"""
Set to crew list to all available crew
"""
crew = getIdNumbers()
return map(lambda cr: cr.id, crew)
What is the meaning of cr.id here, is id a builtin python function or?
In your example, the reference to cr.id is not a function call. Its accessing a member attribute of the cr variable, which is a placeholder for whatever the crew objects are.
id is the name of a builtin function, yes. But there is no way to know if its being used under the hood in these objects without seeing the actual class definitions.
As an example... if this were, say, a django application, model instances have id member attributes that give you the database id of that record. Its part of the design of the class for that framework.
Even though I am assuming its an attribute... for all we know it could also be a computed property which is similar to a method call that acts like an attribute. It could be doing more logic that it seems when looking at your example.
Lastly, since the cr.id could be anything, it could even be a method and the map is returning a lis of callables: cr.id()
cr.id isn't a builtin function (unless you've assigned it to be...), it's a normal member of the cr object there.
id(cr) would be an invocation of that builtin and would return the identity of cr.
I think the real problem here is that you don't understand the code you have posted.
In this context you need to understand map and lambda.
map is a function which applies a function to each element of a list and returns this as a list:
>>> def func(a):
... return a * 2
...
>>> map(func, [1,2,3])
[2, 4, 6]
lambda can be seen as a shortcut to create functions. The above could be written with lambda:
>>> func = lambda a: a * 2
>>> map(func, [1,2,3])
[2, 4, 6]
So what your code map(lambda cr: cr.id, crew) is doing: It returns a list of the id attribute from each of the objects in the list crew.
The problem is that this code is actually not pretty good. You can write the same function with a list comprehension, which is much more intuitive:
def getCrewListAll(self):
return [cr.id for cr in getIdNumbers()]
there is a built in id function but may or may not be related to this, depending on the implementation of that object, either way id here is a member/property of that object.
If you are curious to see what kind of members/fields that object has you can do dir(crew[0]) assuming its retuning at least one, and if its properly document you can also do this help(crew[0].id)
Related
I am writing a custom class which extends the default python lists by adding some new functions such as shuffling , adding, multiplying etc.
The code goes something like this:
class xlist(list):
def __init__(self, original_list: list):
self._olist = original_list
def sumall(self) -> int:
sum = 0
for e in self._olist:
sum += e
return sum
...
But while doing some calculations I needed to get the type of a instance of a xlist. I want to do something like this :
>>> from xlist import xlist
>>> x = xlist([1, 2, 3])
>>> type(x)
When I do this I get <class 'xlist.xlist'> , but I want it to return list.
I am little confused about Metaclasses which seems to be able to solve the problem.
Any Help?
Why do you expect type(x) to return list if you're really creating an xlist? Your xlist inherits from list, so every xlist object is an instance of a list since it inherits from it all of its behaviour (and extends by adding some new functionality).
Note that:
x = xlist([1, 2, 3])
isinstance(x, list)
returns True. You might also want to have a look at Difference between type() and isinstance()
There are two ways for Python to check the class of an object - one is calling type and the other is checking the __class__ slot.
Most times both return the samething, but one can modify the class (for example, by customizing attribute access on the metaclass) so that __class__ will "lie" and Python code using myobject.__class__ will get the "false" information.
However, underneath, the "true" __class__ slot in the type object will always hold a reference to the real type - and this can't be falsified. Any C extension, and maybe even a few Python extensions, and the return to type(myobject) itself will see the real class.
Changing the contents of this slot actually changes the class of your instance. It is feasible from pure Python with a simple = attribution - but there are guards in place on this assignment to ensure it is only done across types that have a compatible memory layout. Forcing it to change to an incompatible type (Via an extension, or ctypes) will get your Python runtime to segfault.
All that said, there is no reason to lie about your class to users of your class -they should be able to "see" that the object the are holding is a xlist and not a list, and that xlists are also list objects, due to inheritance. Falsifying this information would be a rather bad practice. On the other hand, there are few calls, in Python stdlib itself, that require the underlying object to really be a list and won't accept subtypes (notoriously Python´s json.dumps serialization). That call has a native code path and won't be fooled by customizing access to __class__. However, the same call also has a Python only codepath that is triggered by setting some of the optional arguments (for example, by passing ident=4 on the call). If that is you are trying to achieve (fool some code that requires an strict list) you have to heck that, and if it is Python code, it is doable. In the specific case of json.dump, you'd be better monkeypatching the encoder to use a less strict check than to falsify your object - because I think the code there uses type for the checing.
So, with all of the above said, the "metaclass trick" to Falsify the return of .__class__ can be as simple as:
class xlist(list, metaclass=Meta):
def __init__(self, original_list: list):
self._olist = original_list
def sumall(self) -> int:
sum = 0
for e in self._olist:
sum += e
return sum
#property
def __class__(self):
return list
In Swift we can do the following, at any scope (including inside another function):
var X:Int = 3
var twiceX:Int{
return 2*X
}
print(twiceX) //6
This means we can call a getter function without using the "()" syntax. Any function that takes no argument and return one value can also be implemented as a computer property. Additionally, it is also possible to provide a setter function.
I see that it is possible to make computed properties that belong to classes, using #property declarator, but I see no way to make this a global one. I would expect anything possible at class scope, should be possible at global scope.
Are there global computed properties in Python?
Remarks: I understand that it is mostly a synthetic sugar, that eliminates one pair of ‘()’ every call. However, there are cases where a property is more intuitive than a function. An example is:
queue = [1,4,7]
def current():
return queue[0]
This is used for the same reason that computed properties is seen in classes: as a presentation of a property, without storing the same information twice.
No. Variable lookup and attribute lookup are completely separate mechanisms in Python. What is possible in one is not necessarily possible in the other, and in this case, there is no equivalent of property for variables.
There is one hacky way if your usage is only to write your property out in a command-line, but you always get a string (and you can do any evaluations in addition). I sometimes use this for making nifty command-line syntax sugar when running interactive shells. This is to override the __repr__ method of a wrapper class (your property maker in the question's terms):
queue = [1, 2, 3, 4, 5]
class currentQueueProp:
def __init__(self, transform=lambda x: x):
self.transform = transform
def __repr__(self, transform = lambda x: x):
return str(self.transform(queue[0]))
current = currentQueueProp()
twice_current = currentQueueProp(lambda x: 2*x)
queue[0] = 3
print(current, twice_current) # What you expect
do note that current and twice_current are your class, and not the current value of the queue. This can get confusing since
>>> x = twice_current
>>> x
will appear to show 3 (continuing from the previous example), but of course, x is of type currentQueueProp, and you cannot use arithmetic on it etc:
f(x) # Not equivalent to f(3)
I know it's not possible to assign a new value to a variable passed as a parameter to a function.
>>> a = 1
>>> def foo(bar):
... bar = 2
...
>>> foo(a)
>>> a
1
But it is possible to modify it with methods.
>>> a = [1, 2]
>>> def foo(bar):
... bar.append(3)
...
>>> foo(a)
>>> a
[1, 2, 3]
But is there a method to replace assignation (giving the variable a whole new value). Something to make my first example work :
>>> a = 1
>>> def foo(bar):
... bar.assign(2)
...
>>> foo(a)
>>> a
2
The only alternatives I found are global variables and designing my own classes.
So my questions are :
Is there such method? (or alternative?)
If there isn't, I must be more a design choice than a oversight. Why this choice? If there are methods to modify a part of the value/content, why not a method to replace/give a whole new value/content?
Everything in python is an object, and objects in python are mutable, except when they are not. Basic types like strings, numbers (int, float) are not mutable ie. 1 is always 1, and you can never make 1 something else.
This is actually the case with most so called object oriented languages and is more of an optimization.
As you said, you would need to create your own Object that wraps the immutable types in order to mutate the internals of your new object. You can even create a very simple class to do this
class Mutatable:
def __init__(self, value):
self.value = value
def assign(self, value):
# in python you cannot overload the = (assignment) operator
self.value = value
Now from your example you can say
>>> a = Mutatable(1)
>>> def foo(bar):
... bar.assign(2)
...
>>> foo(a)
>>> a.value
out: 2
As some of the other posters mentioned. General programming advice. Overuse of mutations creates for very hard to debug applications. Functions that return values and raise Exceptions are way easier to test and debug.
First off, every every thing in python is object (except some singleton and interns) and every object exist in a scope contain global, local, built-in and enclosing scopes. And the main purpose of using scopes is obviously preserving a set of command and script which are following a specific aim.
Therefore it's not reasonable to destroy this architecture by letting variables in different scopes to impact each other.
But in Python has provided us with some tools in order to make some variables available in upper scope1, like global statement.
Note: Regarding the second example, remember that changing a mutable object inside the function may impact the caller and that's because mutable objects like lists actually are a container of pointers to the actual objects and when you change one pointer it will affect on the main object.
1. The hierarchy of scopes in python from inner to outer is: Local, Enclosing, Global, Built-in. Known as LEGB manner.
It is a consequence of two design decisions. First, functions arguments in Python are passed by assignment. That is, if you have a call like
foo(a)
it translates to, roughly
bar = a
<function body, verbatim>
That's why you can't just pass a pointer to any variable as you would in, say, C. If you want to mutate a function argument, it must have some mutable internal structure. That's where the second design decision comes in: integers in Python are immutable, along with other types including other kinds of numbers, strings or tuples. I don't know the original motivation behind this decision, but I see two main advantages:
easier for a human to reason about the code (you can be sure your integer does not magically change when you pass it to a function)
easier for a computer to reason about the code (for the purpose of optimization or static analysis), because a lot of function arguments are just numbers or strings
My personal opinion is that you should avoid functions that mutate their arguments where possible. At the very least, they should be methods and mutate the corresponding object. Otherwise the code becomes error-prone and hard to maintain and test. Therefore I fully support this immutability, and try to use immutable objects everywhere.
If you want to change the value of a variable in some function without global or return instructions, then you can pass its name in function parameters and use globals() :
>>> def foo(bar):
globals()[bar] = 3
>>> x = 7
>>> x
7
foo('x')
>>> x
3
Let's say we have a class which has an instance method that accepts another instance of that class, and then returns a new instance of that class.
An example of an this type of class is an integer. It has the __mul__ method, which accepts another integer and returns an integer, which is the product of both numbers.
Here's the problem. I have a class that implements a method like __mul__. I have a list of instances of this class, and I want to apply the aforementioned method of the last object to the object before it, then take the result of that and apply it to the one before it, etc., until we have processed the entire list, and have ourselves one object.
A concrete example looks like this. Imagine we have a list of objects...
my_objs = [do, re, me, fa, so, la, te, do]
... And imagine they have the "combine" method, which follows the pattern outlined above, and we want to apply the procedure I outlined to it. You might think of it like this ...
my_objs_together = do.combine(re.combine(me.combine(fa.combine(so.combine(la.combine(te.combine(do)))))))
That's pretty gnarly, obviously. This makes me want to write a generic function like this...
def together(list_of_objects, method_name):
combined = list_of_objects[0]
for obj in list_of_objects[1:]:
combined = getattr(combined, method_name)(obj)
return combined
...But it occurs to me that there's likely already a standard library function that does this, right?
It's reduce! (I was in the middle of writing the question when I found it :/)
https://docs.python.org/2/library/functions.html#reduce
Apply function of two arguments cumulatively to the items of iterable,
from left to right, so as to reduce the iterable to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5).
I have a function. Inside that I'm maintainfing a dictionary of values.
I want that dictionary to be maintained between different function calls
Suppose the dic is :
a = {'a':1,'b':2,'c':3}
At first call,say,I changed a[a] to 100
Dict becomes a = {'a':100,'b':2,'c':3}
At another call,i changed a[b] to 200
I want that dic to be a = {'a':100,'b':200,'c':3}
But in my code a[a] doesn't remain 100.It changes to initial value 1.
I need an answer ASAP....I m already late...Please help me friends...
You might be talking about a callable object.
class MyFunction( object ):
def __init__( self ):
self.rememberThis= dict()
def __call__( self, arg1, arg2 ):
# do something
rememberThis['a'] = arg1
return someValue
myFunction= MyFunction()
From then on, use myFunction as a simple function. You can access the rememberThis dictionary using myFunction.rememberThis.
You could use a static variable:
def foo(k, v):
foo.a[k] = v
foo.a = {'a': 1, 'b': 2, 'c': 3}
foo('a', 100)
foo('b', 200)
print foo.a
Rather than forcing globals on the code base (that can be the decision of the caller) I prefer the idea of keeping the state related to an instance of the function. A class is good for this but doesn't communicate well what you are trying to accomplish and can be a bit verbose. Taking advantage of closures is, in my opinion, a lot cleaner.
def function_the_world_sees():
a = {'a':1,'b':2,'c':3}
def actual_function(arg0, arg1):
a[arg0] = arg1
return a
return actual_function
stateful_function = function_the_world_sees()
stateful_function("b", 100)
stateful_function("b", 200)
The main caution to keep in mind is that when you make assignments in "actual_function", they occur within "actual_function". This means you can't reassign a to a different variable. The work arounds I use are to put all of my variables I plan to reassign into either into a single element list per variable or a dictionary.
If 'a' is being created inside the function. It is going out of scope. Simply create it outside the function(and before the function is called). By doing this the list/hash will not be deleted after the program leaves the function.
a = {'a':1,'b':2,'c':3}
# call you funciton here
This question doesn't have an elegant answer, in my opinion. The options are callable objects, default values, and attribute hacks. Callable objects are the right answer, but they bring in a lot of structure for what would be a single "static" declaration in another language. Default values are a minor change to the code, but it's kludgy and can be confusing to a new python programmer looking at your code. I don't like them because their existence isn't hidden from anyone who might be looking at your API.
I generally go with an attribute hack. My preferred method is:
def myfunct():
if not hasattr(myfunct, 'state'): myfunct.state = list()
# access myfunct.state in the body however you want
This keeps the declaration of the state in the first line of the function where it belongs, as well as keeping myfunct as a function. The downside is you do the attribute check every time you call the function. This is almost certainly not going to be a bottleneck in most code.
You can 'cheat' using Python's behavior for default arguments. Default arguments are only evaluated once; they get reused for every call of the function.
>>> def testFunction(persistent_dict={'a': 0}):
... persistent_dict['a'] += 1
... print persistent_dict['a']
...
>>> testFunction()
1
>>> testFunction()
2
This isn't the most elegant solution; if someone calls the function and passes in a parameter it will override the default, which probably isn't what you want.
If you just want a quick and dirty way to get the results, that will work. If you're doing something more complicated it might be better to factor it out into a class like S. Lott mentioned.
EDIT: Renamed the dictionary so it wouldn't hide the builtin dict as per the comment below.
Personally, I like the idea of the global statement. It doesn't introduce a global variable but states that a local identifier actually refers to one in the global namespace.
d = dict()
l = list()
def foo(bar, baz):
global d
global l
l.append(bar, baz)
d[bar] = baz
In python 3.0 there is also a "nonlocal" statement.