Reputation: 1424
I'm refactoring code and wonder if this is possible.
def a(array):
class MyClass(object):
def length():
return len(array)
return MyClass
print(a([1,2,3,4]).length())
print(a([1,2,3,4]))
It returns
4
<class '__main__.a.<locals>.MyClass'>
and i want:
4
4
Trying hard, i read about metaclass
and __new__
but cant figure out how to do it.
or
class a():
def __init__(self, array):
self.array = array
def length(self):
return len(self.array)
print(a([1,2,3,4]).length()) # 4
print(a([1,2,3,4])) # <__main__.a object at 0x7fab704c9e50>
It's not working, it has 50% functionality.
So sad i don't have time right now but with my today's knowledge its impossible to do it with metaclass. In sqlite3 we can use cur.execute("SQL;"), cur.execute("SQL;").fetchone() so it is possible to do it.
class Metaclass(type):
def __new__(metacls, name, bases, attrs):
try:
return attrs['length']()
except KeyError:
pass
return type.__new__(metacls, name, bases, attrs)
def a(array):
class MyClass(metaclass=Metaclass):
def length():
return len(array)
return MyClass
print(a([1,2,3,4]).length()) # <- This is not working.
print(a([1,2,3,4])) # 4
I would like to hear if it could be done better or smarter tham my solution, because using function returning class it's a hack in my opinion.
Studied this code and its impossible to know when to replace returning object, i will retype this to class without function. Just checked same problem with just single class. Had trouble with passing arguments from method to metaclass.
Upvotes: 0
Views: 598
Reputation: 1424
This is what i was doing
import sqlite3
import contextlib
class cur_execute():
def __init__(self, sql, data=[]):
self.sql = sql
self.data = data
def fetchall(self):
with sqlite3.connect('/opt/portal/db/portal.sqlite3') as con:
con.execute('pragma journal_mode=wal;')
con.row_factory = sqlite3.Row
with contextlib.closing(con.cursor()) as c:
for row in c.execute(self.sql, self.data):
yield row
def __iter__(self):
yield from self.fetchall()
for row in cur_execute("SELECT * FROM ITEMS;").fetchall():
print(str(row))
for row in cur_execute("SELECT * FROM ITEMS;"):
print(str(row))
__repr__
and __iter__
are solution for this king of problems.
Upvotes: 0
Reputation: 44828
You can simply define __repr__
for your class and make it return the length of the list as a string:
class a():
def __init__(self, array):
self.array = array
def length(self):
return len(self.array)
def __repr__(self):
return str(self.length())
Example:
>>> print(a([1,2,3,4]))
4
Upvotes: 2