Call an object with special symbols python 3 - python

I have a question about how Python knows certain things. For example, when I write
a_list = ["car", "plane"]
print(a)
Python knows that a_list is a list. How does that work? where is it written in the default modules of python?
I want to create an object that works kinda like a list, but when I want to obtain the item in a specific position, I would want to write
object_list[0]
instead of a method like
object_list.obtain_item(0)
And I would want to create an object doing something like
$"car", "plane"$
# like yo do ["car", "plane"] by default
And I can't inherit from list cause it's prohibited in the project I'm working on.
Is this even possible? I was searching here and on the internet, but I can't even put my question in words to search properly.

To answer your first question, that would be a consequence of the implementation of the __getitem__ method.
class Foo():
def __init__(self, x, y):
self.x = x
self.y = y
def __getitem__(self, ind):
if ind == 0:
return self.x
return self.y
x = Foo(1, 2)
print(x[0])
1
print(x[1])
2
Note that this is a very bare implementation, and I haven't used a list because you said you can't use it.
To answer your second question, that would involve making changes to the fundamental syntax and grammar of the language, which you, as an end user of the language, are currently not entitled to do.

Python knows that a_list is a list. How does that work? where is it
written in the default modules of python?
Python interpreter recognize the list literal and then create a list object. The Python list object is part of the "standard types that are built into the interpreter".
I want to create an object that works kind like a list, but when i
want to obtain the item in a specific position, i would want to write
You can do that use object.getitem(self, key). There is a lot of useful example on Internet.
And i would want to create an object doing something like
$"car", "plane"$
like yo do ["car", "plane"] by default
If you don't want change the Python interpreter, you could have a less "native/hardcore" solution parsing the string and creating the objects that you want by yourself., something like:
>>> def my_parser(s):
... return [i.strip('"') for i in s.strip('$').split(', ')]
...
>>> my_parser('$"car", "plane"$')
['car', 'plane']
>>>

Related

Make my custom list Class return 'list' as type

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

Pass a list or variable number of arguments as method parameters

I was wondering what the best (most pythonic) solution is to pass a list or a variable number of arguments to a function/method.
For example I have to following class:
class Dataset():
def __init__(self, *args):
self.data_set = args
and this is a part of the setter property:
#data_set.setter
def data_set(self, args):
data = []
for item in args:
if type(item) is list:
data = [k for k in item]
break
data.append(item)
self._data_set = data
I searched the web, but coudn't find much on the topic.
My goal here is to design the class constructor such that it works with either a list as given parameter:
ds1 = Dataset([4,3,5])
or variable number or arguments:
ds1 = Dataset(4,3,5)
So, what is the best implementation and am I on the right track?
You can try this,
class Dataset():
def __init__(self, *args):
if isinstance(args[0], list) and len(args) == 1:
print('Received a list')
else:
print('Received:', args)
obj = Dataset(1,2,3)
obj = Dataset([1,2,3], 2)
obj = Dataset([1,2,3])
ouputs:
Received: (1, 2, 3)
Received: ([1, 2, 3], 2)
Received a list
Edit:
This code does what you want in a simple way. Nothing more. There are other ways,
they don't look simple to me.
Your comment is actually an excellent question.
The problem is not in this code, but in what you are asking and the Python language.
You want method overloading, and Python doesn't have it.
Testing argument types is unpythonic because Python is a dynamic typed language.You can do it, but you are restricting your functions usefulness to a specific type.
Testing the argument type also results in a typical if..elif chain.
If you are writing functions take a look at functools.singledispatch decorator.
That eliminates the if..elif chain from code. Using it you can define a base function and register specific implementations for each type. Simple and readable. But this routes to the function implementation based on first argument. Now, for instance methods, this won't work because of self. You can change that, but it doesn't look simple any more.
Because Python doesn't support method/function overloading directly, what you asked is not a common pattern to use.
Now Aran Fey gives you good advice. Coding behaviour like this is uncommon in Python and actually introduces ambiguity. Your API contract becomes unclear. Should I pass a list or varargs. And why the choice? Just because you already have tuples and dicts with *args and *kwargs and want lists too? What about building the "varargs" as the list elements?
You ask for a list or a variable number of arguments, but a list has also a "variable number of arguments" in itself.
So use one or the other. If you go ahead with the initial idea, at least keep it simple like in this answer.

Should I subclass list or create class with list as attribute?

I need a container that can collect a number of objects and provides some reporting functionality on the container's elements. Essentially, I'd like to be able to do:
magiclistobject = MagicList()
magiclistobject.report() ### generates all my needed info about the list content
So I thought of subclassing the normal list and adding a report() method. That way, I get to use all the built-in list functionality.
class SubClassedList(list):
def __init__(self):
list.__init__(self)
def report(self): # forgive the silly example
if 999 in self:
print "999 Alert!"
Instead, I could also create my own class that has a magiclist attribute but I would then have to create new methods for appending, extending, etc., if I want to get to the list using:
magiclistobject.append() # instead of magiclistobject.list.append()
I would need something like this (which seems redundant):
class MagicList():
def __init__(self):
self.list = []
def append(self,element):
self.list.append(element)
def extend(self,element):
self.list.extend(element)
# more list functionality as needed...
def report(self):
if 999 in self.list:
print "999 Alert!"
I thought that subclassing the list would be a no-brainer. But this post here makes it sounds like a no-no. Why?
One reason why extending list might be bad is since it ties together your 'MagicReport' object too closely to the list. For example, a Python list supports the following methods:
append
count
extend
index
insert
pop
remove
reverse
sort
It also contains a whole host of other operations (adding, comparisons using < and >, slicing, etc).
Are all of those operations things that your 'MagicReport' object actually wants to support? For example, the following is legal Python:
b = [1, 2]
b *= 3
print b # [1, 2, 1, 2, 1, 2]
This is a pretty contrived example, but if you inherit from 'list', your 'MagicReport' object will do exactly the same thing if somebody inadvertently does something like this.
As another example, what if you try slicing your MagicReport object?
m = MagicReport()
# Add stuff to m
slice = m[2:3]
print type(slice)
You'd probably expect the slice to be another MagicReport object, but it's actually a list. You'd need to override __getslice__ in order to avoid surprising behavior, which is a bit of a pain.
It also makes it harder for you to change the implementation of your MagicReport object. If you end up needing to do more sophisticated analysis, it often helps to be able to change the underlying data structure into something more suited for the problem.
If you subclass list, you could get around this problem by just providing new append, extend, etc methods so that you don't change the interface, but you won't have any clear way of determining which of the list methods are actually being used unless you read through the entire codebase. However, if you use composition and just have a list as a field and create methods for the operations you support, you know exactly what needs to be changed.
I actually ran into a scenario very similar to your at work recently. I had an object which contained a collection of 'things' which I first internally represented as a list. As the requirements of the project changed, I ended up changing the object to internally use a dict, a custom collections object, then finally an OrderedDict in rapid succession. At least in my experience, composition makes it much easier to change how something is implemented as opposed to inheritance.
That being said, I think extending list might be ok in scenarios where your 'MagicReport' object is legitimately a list in all but name. If you do want to use MagicReport as a list in every single way, and don't plan on changing its implementation, then it just might be more convenient to subclass list and just be done with it.
Though in that case, it might be better to just use a list and write a 'report' function -- I can't imagine you needing to report the contents of the list more than once, and creating a custom object with a custom method just for that purpose might be overkill (though this obviously depends on what exactly you're trying to do)
As a general rule, whenever you ask yourself "should I inherit or have a member of that type", choose not to inherit. This rule of thumb is known as "favour composition over inheritance".
The reason why this is so is: composition is appropriate where you want to use features of another class; inheritance is appropriate if other code needs to use the features of the other class with the class you are creating.

Dynamic variable always linked to a method in Python

I create a tkinter root :
root = tkinter.Tk()
and would like to create a dynamic variable which would be always linked to some property (or is it called a method?) of root :
X = root.winfo_width()
If root's winfo_width() changes, I would like that X is automatically updated.
How to do this?
Is it called an alias ? a dynamic variable ?
If you just want a shorthand,
X = root.winfo_width
print X()
The problem is that, although Python is really dynamic, there are a few things that always do exactly the same thing that can't be changed.
One is simple assignment:
x = ...some complex expression...
This always does the same thing: it evaluates "some complex expression", and then x is changed so that it is now a reference to the result of the expression.
The other is variable evaluation:
x
Simply using a single variable never invokes any code or methods or anything -- in the expression where you use x, x is simply "replaced" by whatever it is referring to.
So doing exactly what you want isn't possible, there's no place to add something dynamic. Method lookup is an obvious alternative:
x.y
Here, you could implement x.getattr to return the thing you need (too tricky), or you could give x a property method y (as in the other answers).
The other thing is that x could refer to a mutable object, and it could be x's contents that change. E.g., if x refers to a dictionary,
x = root.winfo_dimensions()
print x['width']
Then you could make it so that root keeps an instance of that dictionary itself, and updates it when the width changes. Maybe it only keeps one and returns that. But then you can also change the contents from elsewhere, and that's tricky.
I wouldn't do any of this at all and just call root.winfo_width() where needed. Explicit is better than implicit.
Depending on what you need exactly, #property decorator may do the trick (based on #BrenBarn's answer):
class X(object):
#property # <-- this 'decorator' provides the necessary magic
def x(self):
return time.time() # <-- just for example of refresh
def __repr__(self):
return str(self.x)
Now we can do:
>>> x = X()
>>> x
1386929249.63
>>> x
1386929250.27
But that may be a trick linked to the interpreter, but you still can do the following:
>>> x.x
1386929251.14
>>> x.x
1386929253.01
If you have several such "dynamic properties", you can just group them in one class, and access them this way (but this may not be a good idea, in terms of readability, to hide dynamic behavior of a property).
I'll tell you how to make an "alias" of the function, i hope it helps you.
def X():
return root.winfo_width()
You make that definition, so each time you call "X()" you get the value of root.winfo_width(). If the value of root.winfo_wifth() changes, and you call X(), you get the updated value

Referencing Python list elements without specifying indexes

How can I store values in a list without specifying index numbers?
For example
outcomeHornFive=5
someList = []
someList.append(outComeHornFive)
instead of doing this,
someList[0] # to reference horn five outcome
how can i do something like this? The reason is there are many items that I need to reference within the list and I just think it's really inconvenient to keep track of which index is what.
someList.hornFive
You can use another data structure if you'd like to reference things by attribute access (or otherwise via a name).
You can put them in a dict, or create a class, or do something else. It depends what kind of other interaction you want to have with that object.
(P.S., we call those lists, not arrays).
Instead of using a list you can use a dictionary.
See data types in the python documentation.
A dictionary allows you to lookup a value using a key:
my_dict["HornFive"] = 20
You cannot and you shouldn't. If you could do that, how would you refer to the list itself? And you will need to refer to the list itself.
The reason is there are many items that i need to reference within the list and I just think it's really inconvenient to keep track of which index is what.
You'll need to do something of that ilk anyway, no matter how you organize your data. If you had separate variables, you'd need to know which variable stores what. If you had your way with this, you'd still need to know that a bare someList refers to "horn five" and not to, say, "horn six".
One advantage of lists and dicts is that you can factor out this knowledge and write generic code. A dictionary, or even a custom class (if there is a finite number of semantically distinct attributes, and you'd never have to use it as a collection), may help with the readability by giving it an actual name instead of a numeric index.
referenced from http://parand.com/say/index.php/2008/10/13/access-python-dictionary-keys-as-properties/
Say you want to access the values if your dictionary via the dot notation instead of the dictionary syntax. That is, you have:
d = {'name':'Joe', 'mood':'grumpy'}
And you want to get at “name” and “mood” via
d.name
d.mood
instead of the usual
d['name']
d['mood']
Why would you want to do this? Maybe you’re fond of the Javascript Way. Or you find it more aesthetic. In my case I need to have the same piece of code deal with items that are either instances of Django models or plain dictionaries, so I need to provide a uniform way of getting at the attributes.
Turns out it’s pretty simple:
class DictObj(object):
def __init__(self, d):
self.d = d
def __getattr__(self, m):
return self.d.get(m, None)
d = DictObj(d)
d.name
# prints Joe
d.mood
# prints grumpy

Categories

Resources