Why can instance methods be called as class methods in Python 3?

Consider the following class:

class Foo(object):
    def bar(self):
        print(self)

In Python 2 (2.7.13), calling bar() as a class method raises an exception:

>>> Foo.bar('hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got str instance instead)

>>> Foo.bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)

When bar() is called as an instance method it recognizes self as the instance when called without arguments

>>> Foo().bar('hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes exactly 1 argument (2 given)

>>> Foo().bar()
<__main__.Foo object at 0x10a8e1a10>

In Python 3 (3.6.0), when calling bar() as a class method, the first argument is accepted as self:

>>> Foo.bar('hello')
hello

>>> Foo.bar()
 Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() missing 1 required positional argument: 'self'

Calling bar() as an instance method works as in Python 2

>>> Foo().bar('hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 1 positional argument but 2 were given

>>> Foo().bar()
<__main__.Foo object at 0x104ab34a8>

Solution:

On Python 3, Foo.bar is just that bar function you wrote. It takes one parameter, which happens to be named self, and prints it. You can call that function on anything, and it will print whatever argument you pass it.

On Python 2, Foo.bar isn’t quite the bar function you wrote. When you access Foo.bar, Python generates an unbound method object wrapping the bar function. The unbound method object works mostly like the bar function, with the main difference of validating that its first argument is an instance of Foo. You could do

Foo.bar(some_foo_instance)

which would work like some_foo_instance.bar(), but calling Foo‘s implementation, bypassing any overrides in subclasses. You couldn’t do Foo.bar('hello'), though.

Python 3 removed unbound method objects. They don’t exist any more. That makes the language a bit simpler, but it removes the validation unbound method objects used to perform.

Inner classes – Inheritance and overriding their attributes

I’m trying to understand how Django uses python’s metaclasses for it’s database models (options) and came up with the following stripped down code snippet that should roughly mimic Django’s logic.

class DatabaseOptions(object):

    def __init__(self, opts):
        if opts:
            for key, val in opts.__dict__.items():
                if not key.startswith('__') and not callable(val):
                    setattr(self, key, val)


class MetaModel(type):

    def __new__(cls, name, bases, classdict):
        result = super().__new__(cls, name, bases, dict(classdict))

        opts = classdict.pop('DbMeta', None)
        if opts:
            setattr(result, '_db_meta', DatabaseOptions(opts))

        return result


class Model(object, metaclass=MetaModel):

    class DbMeta:
        database = 'default'
        migrate = True


class User(Model):

    class DbMeta(Model.DbMeta):
        database = 'user'


class GroupUser(User):

    class DbMeta(User.DbMeta):
        database = 'group_user'

Using the above code, I would expect the following output:

print(Model._db_meta.database)  # default
print(Model._db_meta.migrate)  # True

print(User._db_meta.database)  # user
print(User._db_meta.migrate)   # True

print(GroupUser._db_meta.database)  # group_user
print(GroupUser._db_meta.migrate)  # True

Instead I get the following exception

>>> python3 test.py 
default
True
user
Traceback (most recent call last):
  File "test.py", line 48, in <module>
    print(User._db_meta.migrate)   # True
AttributeError: 'DatabaseOptions' object has no attribute 'migrate'

My question would be why User.DbMeta does not inherit the migrate attribute from Model.DbMeta? Is there any solution for this kind of problem?

Edit:

According to Daniel’s answer I came up with the following that worked for me:

class DatabaseOptions(object):

    def __init__(self, opts):
        if opts:
            for key in dir(opts):
                if not key.startswith('__'):
                    val = getattr(opts, key, None)
                    if not callable(val):
                        setattr(self, key, val)

Solution:

This isn’t a question about inner classes specifically.

Class attributes are just that, attributes of the class itself. So, the __dict__ of Model.DbMeta contains “database” and “migrate”, but the one of User.DbMeta contains only “database” because that is the only attribute defined by that class.

However, those attributes are shown by dir(); you should probably iterate over the results of calling that on the class in DatabaseOptions rather than __dict__.

How can I pass a python variable from html file to an external js file?

I am seperating my js in my html file to an external js file. In that case how can I pass my uid which is obtaining on session? I have ajax requests and i move all this to external js file?

My external js (su.js) file now is

submitBox = new Vue({
el: "#submitBox",
  data: {
   name: '',
   authType: 'authType',
   email: 'email',
 },
 methods: {
     handelSubmit: function(e) {
           var vm = this;
           data = {};
           data['name'] = this.name;
           data['email'] = this.nemail;
           data['auth-token'] = this.authType;

            $.ajax({
              url: 'http://127.0.0.1:8000/alpha/add/post/',
              data: data,
              type: "POST",
              dataType: 'json',
              success: function(e) {
              if (e.status)
              {
                alert("Success")
                vm.pid=e.pid;
            }
              else {
               alert("Registration Failed") 
              }
          }
            });
            return false;
},
})

In my html file (submit.html) i store the values of authType as


var authType = '{{uid}}';

my views.py is

@csrf_exempt
def submit(request):
    if('is_logged_in' in request.session):
        id = request.session['authToken'];
        return render(request,"submit.html",{'uid':id});
    else:
        return render(request,"submit.html",{});

So, how can I pass the value of authType to external js (su.js) file. It is using vue.js. Can anybody please help to obtain the result for me?

Solution:

Try this. You do not need to declare in your vue. It is already present as a global variable.

el: "#submitBox",
  data: {
   name: '',
   email: 'email',
 },
 methods: {
     handelSubmit: function(e) {
           var vm = this;
           data = {};
           data['name'] = this.name;
           data['email'] = this.nemail;
           data['auth-token'] = authType;

            $.ajax({
              url: 'http://127.0.0.1:8000/alpha/add/post/',
              data: data,
              type: "POST",
              dataType: 'json',
              success: function(e) {
              if (e.status)
              {
                alert("Success")
                vm.pid=e.pid;
            }
              else {
               alert("Registration Failed") 
              }
          }
            });
            return false;
},
})

Filtering the two first matching elements in a list

I have a list of lists sorted in an ascending order, similar to this one:

input = [[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[3,1],[6,1],[6,2]]

I want to filter this list so that the new list would only contain the first two (or the only) element with matching integers in position 0, like so:

output = [[1,1],[1,2],[2,1],[2,2],[3,1],[6,1],[6,2]]

It would be ideal if the remaining elements (the ones which did not meet the criteria) would remain on the input list, while the matching elements would be stored separately.

How do I go about doing this?

Thank you in advance!

Edit: The elements on the index 1 could be virtually any integers, e.g. [[1,6],[1,7],[1,8],[2,1],[2,2]]

Solution:

Pandas

Although this is a bit overkill, we can use pandas for this:

import pandas as pd

pd.DataFrame(d).groupby(0).head(2).values.tolist()

With d the original list. This then yields:

>>> pd.DataFrame(d).groupby(0).head(2).values.tolist()
[[1, 1], [1, 2], [2, 1], [2, 2], [3, 1], [6, 1], [6, 2]]

Note that this will return copies of the lists, not the original lists. Furthermore all the rows should have the same number of items.

Itertools groupby and islice

If the list is ordered lexicographically, then we can use itertools.groupby:

from operator import itemgetter
from itertools import groupby, islice

[e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2)]

this again yields:

>>> [e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2)]
[[1, 1], [1, 2], [2, 1], [2, 2], [3, 1], [6, 1], [6, 2]]

It is also more flexible since we copy the reference to the list, and all lists can have a different number of elements (at least one here).

EDIT

The rest of the values can be obtained, by letting islice work the opposite way: retain everything but the firs two:

[e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2, None)]

we then obtain:

>>> [e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2, None)]
[[1, 3], [1, 4], [2, 3]]

Handling large numbers python 2.7(runtime error)

I have to make a program that finds the n-th element in the following endless sequence:

1 1 2 1 1 2 3 2 1 1 2 3 4 3 2 1......

So here you can see that ‘center’ increments by one and side elements of the ‘center’ reflect each other so we can break this sequence into small groups:

[1][121][12321][1234321]..... 

So the task is to find n-th element in the sequence given n. For example, we take 7 as input and must return 3, because the 7th element in sequence is 3. The problem here is that when n exceeds 10^15 my program shows runtime error, while input can be as large as 10^100000. Here is my code:

n = int(input())
fin = n
number = long(1)
counter = long(0)
while n>0:
    n = n - number
    number = number+2
    counter = counter + 1
mid = long((counter-1)*(2+2*(counter-1))/2+1)

place = long(counter - abs(mid-fin))

if fin==0:
    print 0
else:
    print place

Solution:

We have groups of numbers:

[1] [1 2 1] [1 2 3 2 1] ...

The overall amount of numbers in k groups is:

1 + 3 + 5 + ... + k*2-1 

This is an arithmetic progression, its sum equals to

(1 + k*2-1) * k / 2 = k^2

Now let’s find the number of full groups k that go before n-th number in the sequence.

k = ⌊sqrt(n-1)⌋

Now we know that our n-th number is in group number k+1 that has k*2+1 elements. Let’s discard first k groups (they have k^2 numbers), now we need to find the number with index n-k^2. And its value will be equal to k+1 - |n-k^2 - (k+1)|. For relatively small n we can use this code:

n = int(input())
k = int(math.sqrt(n-1))
print(k+1 - abs(n-k*k - (k+1)))

But seeing the n <= 10^5000000 constraint we cannot simply use math.sqrt, we need other way of finding a square root of a large integer. This SO question could be helpful.

Python multiple inheritance is not showing class variables or method of second inherited base class

Hello awesome community,
I was learning the OOPS concepts with python as a part of my curriculum. I am having a problem with multiple inheritance in python. The following is my code:

#!/usr/bin/env python

class Base1(object):
    def __init__(self):
        self.base1var = "this is base1"


class Base2(object):
    def __init__(self):
        self.base2var = "this is base2"

class MainClass(Base1, Base2):
    def __init__(self):
        super(MainClass, self).__init__()


if __name__ == "__main__":
    a = MainClass()
    print a.base1var
    print a.base2var

and when running, I am getting the following error

print a.base2var
AttributeError: 'MainClass' object has no attribute 'base2var'

If I swap the order of classes inherited, the variable name in the error changes accordingly.

Am I using super() wrong when I want to call the constructors of the two inherited classes?

How can I correctly inherit from multiple base classes and use the variables and methods in the main class without this error?

Thank you.

Solution:

You need to add a super call to Base1 so that Base2’s __init__ will get called after Base1’s. You can also add a super call to Base2. It’s not necessary, but it won’t hurt.

class Base1(object):
    def __init__(self):
        super(Base1, self).__init__()
        self.base1var = "this is base1"

class Base2(object):
    def __init__(self):
        #super(Base2, self).__init__()
        self.base2var = "this is base2"

class MainClass(Base1, Base2):
    def __init__(self):
        super(MainClass, self).__init__()


if __name__ == "__main__":
    a = MainClass()
    print a.base1var
    print a.base2var

output

this is base1
this is base2

BTW, you really should be using Python 3. super is much nicer in modern Python. 🙂

Escape is a shortcut I do not want in pycharm, how to change?

In pycharm escape switches me to the editor window, how to change this?

Solution:

No, currently you cannot easily change the behavior – Escape is, unfortunately, hardcoded for the “Jump to Editor” action. There is an open discussion on the topic (since 2013):

There are though some workarounds for some of the screens you are pushing Escape in – for instance – Terminal.

How do you convert hexadecimal to ternary in Python?

I’m trying to convert any length hexadecimal to ternary (two way), specifically in Python. I’ve tried using int, and that didn’t work. I also tried this library called baseconvert, but that just spits an error, NameError: name 'base' is not defined, when I try to use the base command they give.

Then, I tried this script:

#!/usb/bin/python

def toStr(n,base):
   convertString = "0123456789ABCDEF"
   if n < base:
      return convertString[n]
   else:
      return toStr(n//base,base) + convertString[n%base]

#####################

hex = "6a48f82d8e828ce82b82abc12397812389721389712387912321387913248723081270243872308472384723472304723089547230485728347283470928347087230457340587304857034570345708345034509348509834509834598230948230948203948092348092348092348092385409283092340923409823490823409820394820934809234809abababababab2345098234092349084238903244444444444444444444444444444442430898888888888888888888999999999999999999999997"
# hex = "6A48F82D8E828CE82B82"
# hex = "e30ac3baf3ab3ffedb8a02dfcc962e2c455650c1614d63ba9a058685da6f04f1c282a5214e65a47506d65a7b9a80d85fc7365aabce539a0696ff2157485d720a7368613531323a20646333656537636164333839396538333839316236376137376136356531356362346665383262356465646363623631373237383833633761306232663064366630396461643264316461393937336432663134333338393161653264373534623864316363653835656433656635353865363634626665656135373531363820696e6465782e68746d6c"

print("hex  =", hex)

# dec = int(hex, 16)
# print("dec  =", dec)

tern = (toStr(int(hex, 16),3))
print("tern =", tern)

rehex = (toStr(int(tern, 3),16))
print("rehex  =", rehex)

#####################


# unhex: Convert Hexadecits to Trits
# tern = ""
# for i in hex:
#     digit = (toStr(int(i, 16),3))
#     tern += digit
#     # print("tern =", tern)

#     # print(i)
# print("tern =", tern)

Which does it two-way, but shows this error: RecursionError: maximum recursion depth exceeded in comparison. I want to have any length, so I can’t just increase the maximum recursion depth, because that still won’t work with every length.

Any help is appreciated!

Solution:

Your code works as expected, and does what you want it to do. The problem is that Python by default has a guard for maximum recursion depth (maximum 1000 layers in stack). You can increase it, but this would not be very scalable. What you really want to do is rewrite your code in an iterative fashion.

Your code could look something like that:

def toStr(n, base):
    convertString = "0123456789ABCDEF"
    result = ''
    while n > base:
        result = result + convertString[n%base]
        n = n//base
    if n > 0:
        result = result + convertString[n]
    return result

More info: SO description on max recursion depth

How to do union of several lists?

I was reading this: Combining two lists and removing duplicates, without removing duplicates in original list but my need goes beyond. I have at least 30 lists and I need the union without duplicates of all the lists. Right now my first try was just to use + to just append all the member in one great list and then use set to remove duplicates, but I’m not sure if this is the best solution:

Edit – Adding samples:

list_a = ['abc','bcd','dcb']
list_b = ['abc','xyz','ASD']
list_c = ['AZD','bxd','qwe']
big_list = list_a + list_b + list_c
print list(set(big_list)) # Prints ['abc', 'qwe', 'bcd', 'xyz', 'dcb', 'ASD', 'bxd']

My real question is if this the best way to go with this combination?

Solution:

If I understand correctly what you are trying to do, you can use the set.update method with an arbitrary number of iterable arguments.

>>> lists = [[1,2,3], [3,4,5], [5,6,7]]
>>> result = set()
>>> result.update(*lists)
>>> 
>>> result
{1, 2, 3, 4, 5, 6, 7}

edit: with your sample data:

>>> list_a = ['abc','bcd','dcb']
>>> list_b = ['abc','xyz','ASD']
>>> list_c = ['AZD','bxd','qwe']
>>> 
>>> result = set()
>>> result.update(list_a, list_b, list_c)
>>> result
{'ASD', 'xyz', 'qwe', 'bxd', 'AZD', 'bcd', 'dcb', 'abc'}

Unexpected output from list comprehension

I have an input list as follows:

test_list = ['a', ('abc', 'd'), ['efgh', 'i'], 'jkl']

which I need to flatten, so getting rid of the tuple and list as respective second and third element of test_list

Expected output:

['a', 'abc', 'd', 'efgh', 'i', 'jkl']

I have a problem finding the correct list comprehension for this.
I have tried the following 2 examples:

result = [xs if type(xs) is str else x for xs in test_list for x in xs]
print('result', result) 
# this outputs:
# ['a', 'abc', 'd', 'efgh', 'i', 'jkl', 'jkl', 'jkl']

result = [x if ((type(xs) is list) or (type(xs) is tuple)) else xs for xs in test_list for x in xs]
print('result',result)
#this also outputs:
# ['a', 'abc', 'd', 'efgh', 'i', 'jkl', 'jkl', 'jkl']  

as you can see, it does “flatten” the list, but it repeats the last element based on the number of characters in the last element. Example if the last element of the test_list is 'jklm' then the in the result the last element is repeated 4 times.

I would like to know if there is a list comprehension which flatten my input list to the expected output without repeating the last element.

Solution:

The following nested comprehension will work:

[x for sub in test_list for x in (sub if isinstance(sub, (list, tuple)) else [sub])]

This uses isinstance which should preferred over type(...) and can be given multiple types. If any top level element is not a list or tuple, it is wrapped in a list.