Related
I have a question about performance.
If I have a case when I pass a mutable object to a function and I make changes to that object, I know that in python it will change the value and all the pointers will point to the value that has been changed.
But what is the right way to write code?
Should I use the return statement and assign all over again the pointer to the output of the function to show to the one that reads the code that it is being changed?
How hard is it hurting the performance if you preform an assignment of a pointer to the same memory it is already pointing?
Thanks!
Should use the return statement and assign all over again the pointer to the output of the function to show to the one that reads the code that it is being changed?
No, that would make it more confusing. If you’re going to change an object in place, you should make it obvious, and part of making it obvious is not returning the same object. Take existing Python APIs as inspiration:
>>> import random
>>> a = [1, 2, 3]
>>> random.shuffle(a)
random.shuffle didn’t return anything, so the only thing it could have done was shuffle the list in place.
Performance is irrelevant here.
a) It has no significant effect on the performance.
b) If your function takes a object and changes it, this is a side-effect and you should therefore not return that object. That would be confusing and misleading as it implies that the input is different from the output.
c) If you think you should write code that is useless just to provide information to readers of your code, use comments instead.
For example, if I'm reading some code that works like this:
list_of_objects = function_returning_object_list()
for object in list_of_objects:
do_something(object.param)
isn't object.get_param kind of strange to see if you're just reading the code and don't know that function_returning_object_list() actually does return a list of objects? Without variable typing how do you avoid this kind of confusion through naming conventions?
Hope I'm clear.
This might be mostly an opinion based question but I'll attempt an answer.
Good variable names always help no matter the language. If you have a function with a name, say, get_data, you cannot really deduce that if that data is a single object or a list or what. But instead if you have a class Bunny and some function with the name get_bunnies, it is safe to assume that it will return some kind of collection. Of course there is always the question that whether the collection is a list or a dict for example.
But if you are just reading the code like that, you can quickly deduce that if it is used with keywords, it is a dict, or some derivative of it.
The purpose of Duck Typing is in short that "if it walks like a duck, swims like a duck and quacks like a duck, then it probably is a duck". Meaning that even if the get_bunnies returns some fancy subclass of dict, you should be able to use it like it is actually a dict, as long as it implements the right __dunder__-methods.
Duck typing always of course brings up some problems that strong typing does not, but that is usually just a matter of convention. If you are unsure that what some function will return, you can always test it: in your code, in the interpreter or even looking up the source.
About the "hungarian notation" of naming variables like strName or name_string... I have always agreed with Robert C. Martin that it brings unneeded redundancy to variable names. Of course the reduncancy is not that bad with dynamic typing, but even so, I dislike it. It tends to just make things harder when reading the code and searching through it. Or even more so, when the variable type is changed without changing the name...
If you have neither example code available nor good naming, you will need to either look up the source code, or hope that there is a docstring included in the function definition. If you are in luck and docstrings are defined and up to date, a good IDE will help you a lot to parse that string for you, or even the whole definition of the function, without the need to find the source file yourself.
Well, everything in Python IS indeed an object. Appropriate question here would be if each returned object has param attribute.
In [17]: a = 1
In [18]: type(a)
Out[18]: int
In [19]: b = 'b'
In [20]: type(b)
Out[20]: str
In [21]: c = True
In [22]: type(c)
Out[22]: bool
If You look at the examples above, You'll see that they're objects of type str, int and bool. Problem is that none of those have param attribute.
I constantly see people state that "Everything in Python is an object.", but I haven't seen "thing" actually defined. This saying would lead me to believe that all tokens of any kind are also considered to be objects, including operators, punctuators, whitespace, etc. Is that actually the case? Is there a more concise way of stating what a Python object actually is?
Thanks
Anything that can be assigned to a variable is an object.
That includes functions, classes, and modules, and of course int's, str's, float's, list's, and everything else. It does not include whitespace, punctuation, or operators.
Just to mention it, there is the operator module in the standard library which includes functions that implement operators; those functions are objects. That doesn't mean + or * are objects.
I could go on and on, but this is simple and pretty complete.
Some values are obviously objects; they are instances of a class, have attributes, etc.
>>> i = 3
>>> type(i)
<type 'int'>
>>> i.denominator
1
Other values are less obviously objects. Types are objects:
>>> type(int)
<type 'type'>
>>> int.__mul__(3, 5)
15
Even type is an object (of type type, oddly enough):
>>> type(type)
<type 'type'>
Modules are objects:
>>> import sys
>>> type(sys)
<type 'module'>
Built-in functions are objects:
>>> type(sum)
<type 'builtin_function_or_method'>
In short, if you can reference it by name, it's an object.
What is generally meant is that most things, for example functions and methods are objects. Modules too. Classes (not just their instances) themselves are objects. and int/float/strings are objects. So, yes, things generally tend to be objects in Python. Cyphase is correct, I just wanted to give some examples of things that might not be immediately obvious as objects.
Being objects then a number of properties are observable on things that you would consider special case, baked-in stuff in other languages. Though __dict__, which allows arbitrary attribute assignment in Python, is often missing on things intended for large volume instantiations like int.
Therefore, at least on pure-Python objects, a lot of magic can happen, from introspection to things like creating a new class on the fly.
Kinda like turtles all the way down.
You're not going to find a rigorous definition like C++11's, because Python does not have a formal specification like C++11, it has a reference manual like pre-ISO C++. The Data model chapter is as rigorous as it gets:
Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects. (In a sense, and in conformance to Von Neumann’s model of a “stored program computer,” code is also represented by objects.)
Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. …
The glossary also has a shorter definition:
Any data with state (attributes or value) and defined behavior (methods).
And it's true that everything in Python has methods and (other) attributes. Even if there are no public methods, there's a set of special methods and values inherited from the object base class, like the __str__ method.
This wasn't true in versions of Python before 2.2, which is part of the reason we have multiple words for nearly the same thing—object, data, value; type, class… But from then on, the following kinds of things are identical:
Objects.
Things that can be returned or yielded by a function.
Things that can be stored in a variable (including a parameter).
Things that are instances of type object (usually indirectly, through a subclass or two).
Things that can be the value resulting from an expression.
Things represented by pointers to PyObject structs in CPython.
… and so on.
That's what "everything is an object" means.
It also means that Python doesn't have "native types" and "class types" like Java, or "value types" and "reference types" like C#; there's only one kind of thing, objects.
This saying would lead me to believe that all tokens of any kind are also considered to be objects, including operators, punctuators, whitespace, etc. Is that actually the case?
No. Those things don't have values, so they're not objects.1
Also, variables are not objects. Unlike C-style variables, Python variables are not memory locations with a type containing a value, they're just names bound to a value in some namespace.2 And that's why you can't pass around references to variables; there is no "thing" to reference.3
Assignment targets are also not objects. They sometimes look a lot like values, and even the core devs sometimes refer to things like the a, b in a, b = 1, 2 loosely as a tuple object—but there is no tuple there.4
There's also a bit of apparent vagueness with things like elements of a numpy.array (or an array.array or ctypes.Structure). When you write a[0] = 3, the 3 object doesn't get stored in the array the way it would with a list. Instead, numpy stores some bytes that Python doesn't even understand, but that it can use to do "the same thing a 3 would do" in array-wide operations, or to make a new copy of the 3 object if you later ask for a[0] = 3.
But if you go back to the definition, it's pretty clear that this "virtual 3" is not an object—while it has a type and value, it does not have an identity.
1. At the meta level, you can write an import hook that can act on imported code as a byte string, a decoded Unicode string, a list of token tuples, an AST node, a code object, or a module, and all of those are objects… But at the "normal" level, from within the code being imported, tokens, etc. are not objects.
2. Under the covers, there's almost always a string object to represent that name, stored in a dict or tuple that represents the namespace, as you can see by calling globals() or dir(self). But that's not what the variable is.
3. A closure cell is sort of a way of representing a reference to a variable, but really, it's the cell itself that's an object, and the variables at different scopes are just a slightly special kind of name for that cell.
4. However, in a[0] = 3, although a[0] isn't a value, a and 0 are, because that assignment is equivalent to the expression a.__setitem__(0, 3), except that it's not an expression.
I have the following in a Python script:
setattr(stringRESULTS, "b", b)
Which gives me the following error:
AttributeError: 'str' object has no attribute 'b'
Can any-one telling me what the problem is here?
Don't do this. To quote the inestimable Greg Hewgill,
"If you ever find yourself using quoted names to refer to variables,
there's usually a better way to do whatever you're trying to do."
[Here you're one level up and using a string variable for the name, but it's the same underlying issue.] Or as S. Lott followed up with in the same thread:
"90% of the time, you should be using a dictionary. The other 10% of
the time, you need to stop what you're doing entirely."
If you're using the contents of stringRESULTS as a pointer to some object fred which you want to setattr, then these objects you want to target must already exist somewhere, and a dictionary is the natural data structure to store them. In fact, depending on your use case, you might be able to use dictionary key/value pairs instead of attributes in the first place.
IOW, my version of what (I'm guessing) you're trying to do would probably look like
d[stringRESULTS].b = b
or
d[stringRESULTS]["b"] = b
depending on whether I wanted/needed to work with an object instance or a dictionary would suffice.
(P.S. relatively few people subscribe to the python-3.x tag. You'll usually get more attention by adding the bare 'python' tag as well.)
Since str is a low-level primitive type, you can't really set any arbitrary attribute on it. You probably need either a dict or a subclass of str:
class StringResult(str):
pass
which should behave as you expect:
my_string_result = StringResult("spam_and_eggs")
my_string_result.b = b
EDIT:
If you're trying to do what DSM suggests, ie. modify a property on a variable that has the same name as the value of the stringRESULTS variable then this should do the trick:
locals()[stringRESULTS].b = b
Please note that this is an extremely dangerous operation and can wreak all kinds of havoc on your app if you aren't careful.
I read on another Stack Overflow question that Python was just like Ruby, as it relates to "everything's an object," and everything in Python was an object, just like Ruby.
Is this true? Is everything an object in Python like Ruby?
How are the two different in this respect or are they really the same? For example, can you take a number and do the Ruby stuff I've seen like:
y = 5.plus 6
Can that be done the same way in Python?
DiveIntoPython - Everything Is an Object
Everything in Python is an object, and almost everything has attributes and methods. All functions have a built-in attribute __doc__, which returns the doc string defined in the function's source code. The sys module is an object which has (among other things) an attribute called path. And so forth.
Still, this begs the question. What is an object? Different programming languages define “object” in different ways. In some, it means that all objects must have attributes and methods; in others, it means that all objects are subclassable. In Python, the definition is looser; some objects have neither attributes nor methods (more on this in Chapter 3), and not all objects are subclassable (more on this in Chapter 5). But everything is an object in the sense that it can be assigned to a variable or passed as an argument to a function (more in this in Chapter 4).
Ruby Docs - To Ruby From Python
As with Python, in Ruby,... Everything is an object
So there you have it from Ruby's own website: in Python everything is an object.
While everything is an object in Python, it differs from Ruby in its approach to resolving names and interacting with objects.
For example, while Ruby provides you with a 'to_s' method on the Object base class, in order to expose that functionality, Python integrates it into the string type itself - you convert a type to a string by constructing a string from it. Instead of 5.to_s, you have str(5).
Don't be fooled, though. There's still a method behind the scenes - which is why this code works:
(5).__str__()
So in practice, the two are fundamentally similar, but you use them differently. Length for sequences like lists and tuples in Python is another example of this principle at work - the actual feature is built upon methods with special names, but exposed through a simpler, easier-to-use interface (the len function).
The Python equivalent to what you wrote in your question would thus be:
(5).__add__(6)
The other difference that's important is how global functions are implemented. In Python, globals are represented by a dictionary (as are locals). This means that the following:
foo(5)
Is equivalent to this in Python:
globals()["foo"].__call__(5)
While Ruby effectively does this:
Object.foo(5)
This has a large impact on the approach used when writing code in both languages. Ruby libraries tend to grow through the addition of methods to existing types like Object, while Python libraries tend to grow through the addition of global functions to a given module.
"everything" is a tad of an overbid, for both Python and Ruby -- for example, if is not "an object", rather it's a keyword used to start a conditional statement or (in Python) inside list comprehensions and generator expressions. The enthusiasm of finding out that functions, classes, methods, and all sort of such things that aren't really objects in (say) C++, are objects in Ruby or Python, causes such enthusiasm. Other things may be objects in Ruby but not Python or viceversa (code blocks, regular expressions, ...).
In answer to your second question, yes:
>>> (1).__add__(2)
3
Yep, as far as I know everything is an object in Python. Certainly the primitive and builtin types (int, long, str, float, etc.) can be subclassed - and in fact the types themselves are objects. Functions are objects, classes are objects, even code blocks are objects in a sense... I can't think of anything in Python that can't be treated as an object.
To add a comment to other people's excellent answers: everything is an object, but some – notably strings and numeric types – are immutable. This means that these types behave the way they do in languages like C or Java (where integers, etc. are not objects) with respect to assignment, parameter passing, etc, and you never have to worry about traps caused by pass-by-reference. It's rather a good solution :-)
Hello and answer is out of the bat not everything, reference is more complete than that and offers many more avenues, within Python 3.8.5 for example Delimiters, Operators and Keywords are not objects. stackoverflow.com/a/66374328/11554034
Have explained it with some detail in that link feel free to check it along.
Anyway, next one says that statement you can correct it by saying (something more correct, although if still can be more completed feel free):
"Everything in a logical line that is not NEWLINE, INDENT, DEDENT, Space bar Character, Operator, Keyword or Delimiter is an object in Python."
Cheers.
Yes, everything is object in Python as long as I researched.
The documentation says below:
Objects are Python’s abstraction for data. All data in a Python
program is represented by objects or by relations between objects.
Every object has an identity, a type and a value.
And, I also checked the type of each value and if each of them is the instance of a particular class as shown below:
from types import FunctionType
class Person:
pass
def test():
pass
print(type("Hello"), isinstance("Hello", str))
print(type(100), isinstance(100, int))
print(type(100.23), isinstance(100.23, float))
print(type(100 + 2j), isinstance(100 + 2j, complex))
print(type(True), isinstance(True, bool))
print(type(None), isinstance(None, type(None)))
print(type([]), isinstance([], list))
print(type(()), isinstance((), tuple))
print(type({}), isinstance({}, dict))
print(type({""}), isinstance({""}, set))
print(type(Person), isinstance(Person, type))
print(type(test), isinstance(test, FunctionType))
Output:
<class 'str'> True
<class 'int'> True
<class 'float'> True
<class 'complex'> True
<class 'bool'> True
<class 'NoneType'> True
<class 'list'> True
<class 'tuple'> True
<class 'dict'> True
<class 'set'> True
<class 'type'> True
<class 'function'> True