Python - Classes and objects - python-2.7

This may appear like a very trivial question but I have just started learning python classes and objects. I have a code like below.
class Point(object):
def __init__(self,x,y):
self.x = float(x)
self.y = float(y)
def __str__(self):
return '('+str(self.x)+','+str(self.y)+')'
def main():
p1 = Point(pt1,pt2)
p2 = Point(pt3,pt4)
p3 = Point(pt5,pt6)
p4 = Point(pt7,pt8)
parray = [p1,p2,p3,p4]
print " Points are", p1,p2,p3,p4
print "parray",parray
I m getting the below Output :
Points are (4.0,2.0) (4.0,8.0) (4.0,-1.0) (100.0,1.0)
parray - intersection.Point object at 0x7ff09f00a550, intersection.Point object at 0x7ff09f00a410, intersection.Point object at 0x7ff09f00a590
My question is why are the addresses of objects assigned to array while I get the values while printing the objects?
Can someone suggest a way to get the values returned by class in array in main function?

When you print an object as an individual argument to a print statement in Python 2 or the print() function in Python 3, Python calls str on the object before printing it out.
When you put the object inside a container like a list and print the list, the list gets str called on it, but it in turn calls repr on each of the items it contains, rather than str. To understand why, look at the list [1, '2, 3', 4] and imagine what it would look like if the quotation marks were not included in the output when it was printed. The quotation marks are part of the '2, 3' string's repr.
So to make your class work the way you want, either rename your __str__ method to __repr__ (which will also work for str calls, since the default implementation of __str__ is to call __repr__), or add an additional __repr__ method. Sometimes it's useful to have a __repr__ that returns a less ambiguous string than __str__ does (for instance, it might name the class as well as the arguments). One common convention is to make __repr__ return a string that could be evaled to get an equivalent object again. For your class, that could look like:
def __repr__(self):
return "{}({!r}, {!r})".format(type(self).__name__, self.x, self.y)
I'd also recommend using string formatting like this (or the older %s style if you prefer), rather than concatenating lots of strings together to build your result.

Python containers, e.g. lists use an objects __repr__ method when printing their contents, not their __str__, Define __repr__ instead:
def __repr__(self):
return '('+str(self.x)+','+str(self.y)+')'
If you want a more detailed explanation of __repr__ vs __str__ see here

Related

Pass capitalised variables to django settings.configure() [duplicate]

Does python have the ability to create dynamic keywords?
For example:
qset.filter(min_price__usd__range=(min_price, max_price))
I want to be able to change the usd part based on a selected currency.
Yes, It does. Use **kwargs in a function definition.
Example:
def f(**kwargs):
print kwargs.keys()
f(a=2, b="b") # -> ['a', 'b']
f(**{'d'+'e': 1}) # -> ['de']
But why do you need that?
If I understand what you're asking correctly,
qset.filter(**{
'min_price_' + selected_currency + '_range' :
(min_price, max_price)})
does what you need.
You can easily do this by declaring your function like this:
def filter(**kwargs):
your function will now be passed a dictionary called kwargs that contains the keywords and values passed to your function. Note that, syntactically, the word kwargs is meaningless; the ** is what causes the dynamic keyword behavior.
You can also do the reverse. If you are calling a function, and you have a dictionary that corresponds to the arguments, you can do
someFunction(**theDictionary)
There is also the lesser used *foo variant, which causes you to receive an array of arguments. This is similar to normal C vararg arrays.
Yes, sort of.
In your filter method you can declare a wildcard variable that collects all the unknown keyword arguments. Your method might look like this:
def filter(self, **kwargs):
for key,value in kwargs:
if key.startswith('min_price__') and key.endswith('__range'):
currency = key.replace('min_price__', '').replace('__range','')
rate = self.current_conversion_rates[currency]
self.setCurrencyRange(value[0]*rate, value[1]*rate)

Different display for pringing same variable in python 2.7.11 class method

I am learning python just now, and confusing a lot question of python.
Below is one question:
class people:
def __init__(self,name):
self.name = name
print self.name
p = people('test')
test
p.name
'test'
why different output for people('test') and p.name? string test with/without single quote?
When you explicitly print something, you get the str() of that object. When you type an expression in the Python interpreter, you get the repr() of that object. Generally speaking, repr is more detailed, and gives some indication of the type of the object; often it is identical to a Python expression that would create that object. In particular, repr of a string is always enclosed in quotes, so that you can tell that it is a string.

Duplicating without referencing in python

How can i duplicate a list of lists (or any other types) in a way that the resulting lists are new objects and not references to the old ones? As an example i have the following list of lists:
l=[[1,2],[3,4]]
what i want as result is:
l=[[1,2],[3,4],[1,2],[3,4]]
If i do l*=2 the new sub-lists are references to the old sub-lists.
Doing l[0].append("python") will result in
l=[[1,2,'python'],[3,4],[1,2,'python'],[3,4]]
Also creating a new list like:
l2=list(l)
or
l2=l[:]
doesn't solve the problem. I want to have new sub-lists which are independent of their origin and which upon changing have no impact on their old fellows. How can i do this i python?
In general, the best way to copy a nested data structure so that copies get made of all the references (not just the ones at the top level) is to use copy.deepcopy. In your nested list example, you can do:
l.extend(copy.deepcopy(l))
deepcopy will still work even if the data structure contains references to itself, or multiple references to the same object. It usually works for objects stored as attributes on an instances of custom classes too. You can define a __deepcopy__ method if you want to give a class special copying behavior (e.g. if some of its attributes are bookkeeping data that shouldn't be copied).
Here's a version of your nested list example code using instances of a linked list class rather than Python lists. copy.deepcopy does the right thing!
class linked_list(object):
def __init__(self, value, next=None):
self.value = value
self.next = next
def __repr__(self):
if self.next is not None:
return "({!r})->{!r}".format(self.value, self.next)
else:
return "({!r})".format self.value
lst = linked_list(linked_list(1, linked_list(2)),
linked_list(linked_list(3, linked_list(4))))
print(lst) # prints ((1)->(2))->((3)->(4))
lst.next.next = copy.deepcopy(lst)
print(lst) # prints ((1)->(2))->((3)->(4))->((1)->(2))->((3)->(4))
lst.value.value = 5
print(lst) # prints ((5)->(2))->((3)->(4))->((1)->(2))->((3)->(4))

Python - null object pattern with generators

It is apparently Pythonic to return values that can be treated as 'False' versions of the successful return type, such that if MyIterableObject: do_things() is a simple way to deal with the output whether or not it is actually there.
With generators, bool(MyGenerator) is always True even if it would have a len of 0 or something equally empty. So while I could write something like the following:
result = list(get_generator(*my_variables))
if result:
do_stuff(result)
It seems like it defeats the benefit of having a generator in the first place.
Perhaps I'm just missing a language feature or something, but what is the pythonic language construct for explicitly indicating that work is not to be done with empty generators?
To be clear, I'd like to be able to give the user some insight as to how much work the script actually did (if any) - contextual snippet as follows:
# Python 2.7
templates = files_from_folder(path_to_folder)
result = list(get_same_sections(templates)) # returns generator
if not result:
msg("No data to sync.")
sys.exit()
for data in result:
for i, tpl in zip(data, templates):
tpl['sections'][i]['uuid'] = data[-1]
msg("{} sections found to sync up.".format(len(result)))
It works, but I think that ultimately it's a waste to change the generator into a list just to see if there's any work to do, so I assume there's a better way, yes?
EDIT: I get the sense that generators just aren't supposed to be used in this way, but I will add an example to show my reasoning.
There's a semi-popular 'helper function' in Python that you see now and again when you need to traverse a structure like a nested dict or what-have-you. Usually called getnode or getn, whenever I see it, it reads something like this:
def get_node(seq, path):
for p in path:
if p in seq:
seq = seq[p]
else:
return ()
return seq
So in this way, you can make it easier to deal with the results of a complicated path to data in a nested structure without always checking for None or try/except when you're not actually dealing with 'something exceptional'.
mydata = get_node(my_container, ('path', 2, 'some', 'data'))
if mydata: # could also be "for x in mydata", etc
do_work(mydata)
else:
something_else()
It's looking less like this kind of syntax would (or could) exist with generators, without writing a class that handles generators in this way as has been suggested.
A generator does not have a length until you've exhausted its iterations.
the only way to get whether it's got anything or not, is to exhaust it
items = list(myGenerator)
if items:
# do something
Unless you wrote a class with attribute nonzero that internally looks at your iterations list
class MyGenerator(object):
def __init__(self, items):
self.items = items
def __iter__(self):
for i in self.items:
yield i
def __nonzero__(self):
return bool(self.items)
>>> bool(MyGenerator([]))
False
>>> bool(MyGenerator([1]))
True
>>>

Django ugettext_lazy, interpolation and ChoiceField

I want a ChoiceField with these choices:
choices = [(1, '1 thing'),
(2, '2 things'),
(3, '3 things'),
...]
and I want to have it translated.
This does not work:
choices = [(i, ungettext_lazy('%s thing', '%s things', i) % i) for i in range(1,4)]
because as soon as the lazy object is interpolated, it becomes a unicode object - since ChoiceField.choices is evaluated at startup, its choices will be in the language active during Django's startup.
I could use ugettext_lazy('%s things' % i), but that would require a translation for each numeral, which is silly. What is the right way to do this?
In the Django documentation, Translation… Working with lazy translation objects, I see a remark which seems to address your concern here.
Using ugettext_lazy() and ungettext_lazy() to mark strings in models and utility functions is a common operation. When you're working with these objects elsewhere in your code, you should ensure that you don't accidentally convert them to strings, because they should be converted as late as possible (so that the correct locale is in effect). This necessitates the use of the helper function described next.
Then they present django.utils.functional.lazy(func, *resultclasses), which is not presently covered by the django.utils.functional module documentation. However, according to the django.utils.functional.py source code, it "Turns any callable into a lazy evaluated callable.… the
function is evaluated on every access."
Modifying their example from Other uses of lazy in delayed translations to incorporate your code, the following code might work for you.
from django.utils import six # Python 3 compatibility
from django.utils.functional import lazy
from django.utils.safestring import mark_safe
choices = [
(i, lazy(
mark_safe(ungettext_lazy('%s thing', '%s things', i) % i),
six.text_type
)# lazy()
for i in range(1,4)
]
Also, the django.utils.functional module documentation does mention a function decorator allow_lazy(func, *resultclasses). This lets you write your own function which takes a lazy string as arguments. "It modifies the function so that if it's called with a lazy translation as the first argument, the function evaluation is delayed until it needs to be converted to a string." lazy(func, *resultclasses) is not a decorator, it modifies a callable.
N.B. I haven't tried this code in Django. I'm just passing along what I found in the documentation. Hopefully it will point you to something you can use.
For those who encounter this question. Unfortunately, #Jim DeLaHunt's answer doesn't completely work - it's almost there, but not exactly what needs to be done.
The important distinctions are:
What you need to warp with lazy is a function that'd return you a text value, not another lazy translation object, or you'll likely see weird <django.utils.functional.__proxy__ at ...> instead of the actual text (IIRC Django won't go deep down the chain of lazy objects). So, use ungettext, not ungettext_lazy.
You want to do string interpolation only when the wrapped function runs. If you write lazy(f("%d" % 42)) the interpolation would happen too early - in this case Python evaluates eagerly. And don't forget about variable scopes - you can't just refer to the iterator from the wrapped function.
Here, I've used a lambda that receives a number argument and does the interpolation. The code inside lambda is only executed when lazy object is evaluated, that is, when the choice is rendered.
So, the working code is:
choices = [
(
(i, lazy(
lambda cnt: ungettext(u"%(count)d thing",
u"%(count)d things", cnt)
% {"count": cnt},
six.text_type
)(i))
)
for i in [1, 2, 3]
]
This will correctly have the same intended effect as
choices = [
(1, _("1 thing")),
(2, _("2 things")),
(3, _("3 things")),
]
But there will be just a single entry for this in translation database, not multiple ones.
This looks like a situation where you could benefit from the trick taught by Ilian Iliev's blog, Django forms ChoiceField with dynamic values….
Iliev shows a very similar initialiser:
my_choice_field = forms.ChoiceField(choices=get_my_choices())
He says, "the trick is that in this case my_choice_field choices are initialized on server (re)start. Or in other words once you run the server the choices are loaded(calculated) and they will not change until next (re)start." Sounds like the same difficulty you are encountering.
His trick is: "fortunately the form`s class has an init method that is called on every form load. Most of the times you skipped it in the form definition but now you will have to use it."
Here is his sample code, blended with your generator expression:
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_choice_field'] = forms.ChoiceField(
choices=(
(i, ungettext_lazy('%s thing', '%s things', i) % i)
for i in range(1,4)
)# choices=
)# __init__
The generator expression is enclosed in parentheses so that it is treated as a generator object, which is assigned to choices.
N.B. I haven't tried this code in Django. I'm just passing along Iliev's idea.