Function to create a class - python

I'd like something like below. Obviously it's invalid syntax, but is it possible to do something like this in python
def make_class(name):
class name:
def __init__(self):
pass
return name
make_class("Test")
a = Test()

Defining a local class in your case seems useless. I'd do that if I did want to return it. There some disadvantages when defining local classes:
Readability: either the class is really trivial or the function
inevitably grows quite long and its logic is lost in the class
declaration. Also you have an extra level of indentation which might
hurt readability if you have some nested loops somewhere
Performance: the class will be re-constructed at every function call.
This usually wont take a huge amount of time, but it will cost a bit.
If the function you are running is fast this cost may be significant.
There are also some advantages of defining a local class:
Locality: you are generally pretty sure that the class wont be used
outside the function, in ways you didn't expect
Performance: looking up a local variable is significantly faster then
looking up a global variable. If you create a big number of instances
this might improve performance with respect to using a global class.
However it's really really easy to counter this advantage via default
arguments/local variables.
My suggestion would be to simply define the class globally and, if it should be private, use a name that starts with an underscore, like _MyClass, since this is the convention used to denote private items.

If you want to find a way of creating a new class without using class keyword, Python classes are instances of type classes. You can create a class by doing like this.
Person = type("Person",
(),
{
"sayHello": lambda: "Hello there"})
You have Person class now with sayHello function defined beforehand.
If you really want to create your function, you can do like this. Actually this is a very bad way. You need to ask your question properly? What do you want to achive?
def create_class(class_name, superclass, namespace):
return type(class_name, superclass, namespace)
Person = create_class("Person",
(),
{
"sayHello": lambda: "Hello there"})
You can do something like this as well.
name = 'Operations'
body = """
def __init__(self, x, y):
self.x = x
self.y = y
def mul(self):
return self.x * self.y
"""
bases = ()
namespace = {}
exec(body, globals(), namespace)
Operations = type(name, bases, namespace)
print(Operations) # output: <class '__main__.Operations'>
instance = Operations(2, 5)
print(instance.mul()) # output: 10

You can define a class and define functions and such in its constuctor, no need to create a new class each time.
Below shows how you can pass in a variable value, a function and how that function can use the object's attributes and how it can be called from another function within the class itself. A lot of stuff, but hopefully by exploring it you will learn a lot!
class my_class:
def __init__(self, name, cool_function):
self.name = name
self.my_function = cool_function
def test(self):
self.my_function(self)
def test_function(self):
print(self.name)
print("Hello World!")
a = my_class("Dave", test_function)
a.test()
# Prints "Dave" and "Hello World!"

Related

How can I refer to the currently being defined class? [duplicate]

For a recursive function we can do:
def f(i):
if i<0: return
print i
f(i-1)
f(10)
However is there a way to do the following thing?
class A:
# do something
some_func(A)
# ...
If I understand your question correctly, you should be able to reference class A within class A by putting the type annotation in quotes. This is called forward reference.
class A:
# do something
def some_func(self, a: 'A')
# ...
See ref below
https://github.com/python/mypy/issues/3661
https://www.youtube.com/watch?v=AJsrxBkV3kc
In Python you cannot reference the class in the class body, although in languages like Ruby you can do it.
In Python instead you can use a class decorator but that will be called once the class has initialized. Another way could be to use metaclass but it depends on what you are trying to achieve.
You can't with the specific syntax you're describing due to the time at which they are evaluated. The reason the example function given works is that the call to f(i-1) within the function body is because the name resolution of f is not performed until the function is actually called. At this point f exists within the scope of execution since the function has already been evaluated. In the case of the class example, the reference to the class name is looked up during while the class definition is still being evaluated. As such, it does not yet exist in the local scope.
Alternatively, the desired behavior can be accomplished using a metaclass like such:
class MetaA(type):
def __init__(cls):
some_func(cls)
class A(object):
__metaclass__=MetaA
# do something
# ...
Using this approach you can perform arbitrary operations on the class object at the time that the class is evaluated.
Maybe you could try calling __class__.
Right now I'm writing a code that calls a class method from within the same class.
It is working well so far.
I'm creating the class methods using something like:
#classmethod
def my_class_method(cls):
return None
And calling then by using:
x = __class__.my_class_method()
It seems most of the answers here are outdated. From python3.7:
from __future__ import annotations
Example:
$ cat rec.py
from __future__ import annotations
class MyList:
def __init__(self,e):
self.data = [e]
def add(self, e):
self.data.append(e)
return self
def score(self, other:MyList):
return len([e
for e in self.data
if e in other.data])
print(MyList(8).add(3).add(4).score(MyList(4).add(9).add(3)))
$ python3.7 rec.py
2
Nope. It works in a function because the function contents are executed at call-time. But the class contents are executed at define-time, at which point the class doesn't exist yet.
It's not normally a problem because you can hack further members into the class after defining it, so you can split up a class definition into multiple parts:
class A(object):
spam= 1
some_func(A)
A.eggs= 2
def _A_scramble(self):
self.spam=self.eggs= 0
A.scramble= _A_scramble
It is, however, pretty unusual to want to call a function on the class in the middle of its own definition. It's not clear what you're trying to do, but chances are you'd be better off with decorators (or the relatively new class decorators).
There isn't a way to do that within the class scope, not unless A was defined to be something else first (and then some_func(A) will do something entirely different from what you expect)
Unless you're doing some sort of stack inspection to add bits to the class, it seems odd why you'd want to do that. Why not just:
class A:
# do something
pass
some_func(A)
That is, run some_func on A after it's been made. Alternately, you could use a class decorator (syntax for it was added in 2.6) or metaclass if you wanted to modify class A somehow. Could you clarify your use case?
If you want to do just a little hacky thing do
class A(object):
...
some_func(A)
If you want to do something more sophisticated you can use a metaclass. A metaclass is responsible for manipulating the class object before it gets fully created. A template would be:
class AType(type):
def __new__(meta, name, bases, dct):
cls = super(AType, meta).__new__(meta, name, bases, dct)
some_func(cls)
return cls
class A(object):
__metaclass__ = AType
...
type is the default metaclass. Instances of metaclasses are classes so __new__ returns a modified instance of (in this case) A.
For more on metaclasses, see http://docs.python.org/reference/datamodel.html#customizing-class-creation.
If the goal is to call a function some_func with the class as an argument, one answer is to declare some_func as a class decorator. Note that the class decorator is called after the class is initialized. It will be passed the class that is being decorated as an argument.
def some_func(cls):
# Do something
print(f"The answer is {cls.x}")
return cls # Don't forget to return the class
#some_func
class A:
x = 1
If you want to pass additional arguments to some_func you have to return a function from the decorator:
def some_other_func(prefix, suffix):
def inner(cls):
print(f"{prefix} {cls.__name__} {suffix}")
return cls
return inner
#some_other_func("Hello", " and goodbye!")
class B:
x = 2
Class decorators can be composed, which results in them being called in the reverse order they are declared:
#some_func
#some_other_func("Hello", "and goodbye!")
class C:
x = 42
The result of which is:
# Hello C and goodbye!
# The answer is 42
What do you want to achieve? It's possible to access a class to tweak its definition using a metaclass, but it's not recommended.
Your code sample can be written simply as:
class A(object):
pass
some_func(A)
If you want to refer to the same object, just use 'self':
class A:
def some_func(self):
another_func(self)
If you want to create a new object of the same class, just do it:
class A:
def some_func(self):
foo = A()
If you want to have access to the metaclass class object (most likely not what you want), again, just do it:
class A:
def some_func(self):
another_func(A) # note that it reads A, not A()
Do remember that in Python, type hinting is just for auto-code completion therefore it helps IDE to infer types and warn user before runtime. In runtime, type hints almost never used(except in some cases) so you can do something like this:
from typing import Any, Optional, NewType
LinkListType = NewType("LinkList", object)
class LinkList:
value: Any
_next: LinkListType
def set_next(self, ll: LinkListType):
self._next = ll
if __name__ == '__main__':
r = LinkList()
r.value = 1
r.set_next(ll=LinkList())
print(r.value)
And as you can see IDE successfully infers it's type as LinkList:
Note: Since the next can be None, hinting this in the type would be better, I just didn't want to confuse OP.
class LinkList:
value: Any
next: Optional[LinkListType]
It's ok to reference the name of the class inside its body (like inside method definitions) if it's actually in scope... Which it will be if it's defined at top level. (In other cases probably not, due to Python scoping quirks!).
For on illustration of the scoping gotcha, try to instantiate Foo:
class Foo(object):
class Bar(object):
def __init__(self):
self.baz = Bar.baz
baz = 15
def __init__(self):
self.bar = Foo.Bar()
(It's going to complain about the global name 'Bar' not being defined.)
Also, something tells me you may want to look into class methods: docs on the classmethod function (to be used as a decorator), a relevant SO question. Edit: Ok, so this suggestion may not be appropriate at all... It's just that the first thing I thought about when reading your question was stuff like alternative constructors etc. If something simpler suits your needs, steer clear of #classmethod weirdness. :-)
Most code in the class will be inside method definitions, in which case you can simply use the name A.

Methods defined outside class which itself is subsequently imported

Is it OK to define functions outside a particular class, use them in the class, and then import that class elsewhere and use it?
Are there any risks associated with doing that, rather than making all functions methods of the class?
I'm writing this code in python 2.7
For example, make a class like this:
def func(a):
return a
class MyClass():
def class_func(self, thing):
return func(thing)
Then import MyClass into another python script and use its class_func method.
Doing this is okay, and in fact a language feature of python. Functions have access to names of the scope they are defined in, regardless of where they are called from.
For example, you can also do something like this:
factor = 2
def multiply(num):
return num*factor
See this post for some background information.
The "risk" associated with this is that the outside name is explicitly not under your control. It can be freely modified by other parts of your program, without the implication being clear.
Consider this example:
def func(a):
return a
class MyClass(object): # note: you should inherit from object in py2.X!
def class_func(self, thing):
return func(thing)
myinstance = MyClass()
foo = myinstance.class_func(1)
def func(a):
return str(a)
bar = myinstance.class_func(1)
Here, foo and bar will be different, namely the integer 1 and the string "1".
Usually, making this possible is the entire point of using such a structure, however.
It's ok, but if func uses only in MyClass it can be helpful to make it staticmethod and place inside MyClass near class_func:
class MyClass(object):
#staticmethod
def _func(a):
return a
def class_func(self, thing):
return type(self)._func(thing)

Python Class __init__ Confirmation

Im trying to understand Python Classes. I am a little confused around defining the __init__. If I have 4 functions created all taking various input variables. Do I have to assign each variable in the __init__?
class Thing:
def __init__(self, arguments, name, address, phone_number, other):
self.arguments = arguments
self.name = name
self.address = address
self.phone_number = phone_number
self.other = other
def First(self, name):
print self.name
def Arguments(self, arguments):
print self.arguments
def Address(self, address, phone_number):
print self.address + str(self.phone_number)
def Other(self, other):
print self.other
The above is completely made up so please excuse its pointlessness (arguably its point is to illustrate my question so guess its not pointless).
No doubt im going to get loads of down marks for this question for some reason but I have been reading various books (Learning Python The Hard Way, Python For Beginners) and been reading various tutorials online but none of them actually confirm "You must add every variable in the init function". So any help understanding the __init__ a little better would be appreciated.
Firstly: The __init__() function is special in that it is called for you while creating a new instance of a class. Apart from that, it is a function like any other function, you can even call it manually if you want.
Then: You are free to do what you want with the parameters passed to a function. Often, the parameters passed to __init__() are stored inside the object (self) that is being initialized. Sometimes, they are used in other ways and the result then stored in self, like passing a hostname and using that to create a socket - you then only store the socket. You don't have to do anything with the parameters though, you can ignore them like you do in your First() function, which receives a parameter name which is ignored. Note that this parameter name and the similar attribute self.name are different things!
Notes:
It is uncommon to ignore parameters passed to __init__() though, just as it is uncommon to ignore parameters in general. In some cases, they are "reserved" so they can be used by derived classes but typically they are unintended (as with your First() function, I guess).
Check out PEP8, which is a style guide. Adhering to it will make it easier for others to read your code. E.g. First() should be first() instead.
Upgrade to Python 3. I don't think there's any excuse nowadays to learn Python 2 and littley excuse except maintenance to use it in general.
If the variable is logically connected to the object itself, it's good to set it in constructor:
class Student:
def __init__(self, name):
self.name = name
def print_name(self):
print(self.name)
If the variable is just a temporary parameter to some function, then, well, just pass it just as a parameter:
class Cafeteria:
def __init__(self):
pass # nothing
def process(self, student_name):
print(student_name + " got lunch")
In Python you don't have to declare all possible object attributes like you have to do in C++, C#, Java etc. I think it's still good idea to initialize them in constructor to some null value (None, 0), but it's not necessary. This is just fine:
class Cafeteria:
def set_today_menu(self, menu):
self.menu = menu
def process(self, student_name):
print(student_name + " got " + self.menu)
You don't have to, but to access them they need to set somewhere...you can also set defaults outside of any of the defs in a class if you want.
def Class:
RandomVariable = 5
def __init__(self, val):
self.RandomVariable = val
This method is known as your initializer where you insatiate an object and then add attributes to it. A human object, if we were to create a class, may contain a name, age, and gender attributes all of which are bound to the object using the self pointer in the initializer. Also, an initializer may modify global variables as well. If you wanted to count the number of babies born, you would add to a global counter variable from our fictitious human class initializer.

Python, how to keep a non-class method as non-class method?

I am making a set of classes that call functions that were defined in a different module. To know which function they must call, the function is stored as a variable of the class (or at least that was what I tried). However, when I try to call it, it automatically assumes that the function is a class method and passes "self" as an argument, which logically causes an error because the function received too many arguments. Do you know how can I avoid the function becoming a class method.
The code would be like:
# Module A
def func1(a):
print a
def func2(a):
print a,a
# Module B
from A import *
class Parent:
def func():
self.sonFunc("Hiya!")
class Son1:
sonFunc = func1
class Son2:
sonFunc = func2
so = Son1()
s.func()
# Should print "Hiya!"
s = Son2()
s.func()
# Should print "Hiya! Hiya!"
Thanks
What you are doing is somewhat of a nonstandard/odd thing, but this should work:
class Son_1(object):
son_func = staticmethod(func_1)
class Son_2(object):
son_func = staticmethod(func_2)
Normally, staticmethod is used as a decorator, but since decorators are just syntactical sugar, you can use them this way too.
An arguably cleaner but also more advanced way would be with a metaclass:
class HasSonMeta(type):
def __new__(cls, name, bases, attrs):
attrs['son_func'] = staticmethod(attrs.pop('__son_func__'))
return type.__new__(cls, name, bases, attrs)
class Son1(object):
__metaclass__ = HasSonMeta
__son_func__ = func_1
class Son2(object):
__metaclass__ = HasSonMeta
__son_func__ = func_2
Using this form, you could also define the function directly in the class (though then it gets even more confusing to anyone reading this code):
class Son3(object):
__metaclass__ = HasSonMeta
def __son_func__():
pass
While there could be a very narrow/obscure scenario where this would be an optimal implementation, you would probably be better served by putting your functions in a base class and then referring to (or overridding) them as needed in the children.

Classes in python, how to set an attributes

When I write class in python, most of the time, I am eager to set variables I use, as properties of the object. Is there any rule or general guidelines about which variables should be used as class/instance attribute and which should not?
for example:
class simple(object):
def __init(self):
a=2
b=3
return a*b
class simple(object):
def __init(self):
self.a=2
self.b=3
return a*b
While I completely understand the attributes should be a property of the object. This is simple to understand when the class declaration is simple but as the program goes longer and longer and there are many places where the data exchange between various modules should be done, I get confused on where I should use a/b or self.a/self.b. Is there any guidelines for this?
Where you use self.a you are creating a property, so this can be accessed from outside the class and persists beyond that function. These should be used for storing data about the object.
Where you use a it is a local variable, and only lasts while in the scope of that function, so should be used where you are only using it within the function (as in this case).
Note that __init is misleading, as it looks like __init__ - but isn't the constructor. If you intended them to be the constructor, then it makes no sense to return a value (as the new object is what is returned).
class Person(object):
def __init__(self, name):
# Introduce all instance variables on __init__
self.name = name
self.another = None
def get_name(self):
# get_name has access to the `instance` variable 'name'
return self.name
So if you want a variable to be available on more than one method, make
it an instance variable.
Notice my comment on introducing all instance vars on __init__.
Although the example below is valid python don't do it.
class Person(object):
def __init__(self):
self.a = 0
def foo(self):
self.b = 1 # Whoa, introduced new instance variable
Instead initialize all your instance variables on __init__ and set
them to None if no other value is appropriate for them.
I try to imagine what I want the API of my class to look like prior to implementing it. I think to myself, If I didn't write this class, would I want to read the documentation about what this particular variable does? If reading that documentation would simply waste my time, then it should probably be a local variable.
Occasionally, you need to preserve some information, but you wouldn't necessarily want that to be part of the API, which is when you use the convention of appending an underscore. e.g. self._some_data_that_is_not_part_of_the_api.
The self parameter refers to the object itself. So if you need to use on of the class attributes outside of the class you would it call it as the name of class instance and the attribute name. I don't think there is any guideline on when to use self, it all depends on your need. When you are building a class you should try to think about what you will use the variables you creating for. If you know for sure that you will need that specific attribute in the program you are importing your class, then add self.

Categories