I am new to Python. I am trying to create a class which only allows to objects to be created. I am using a private variable instance to keep track of count .
My Code -
class s:
__instance=2
if s.__instance<2:
def __init__(self,x):
s._instance = x
s._instance = s._instance+1
print(s._instance)
a=s(5)
When i run the code i got -
"C:\Users\PIYU\AppData\Local\Programs\Python\Python36\python.exe"
"C:/Users/PIYU/PycharmProjects/PythonProgram/singleton.py"
Traceback (most recent call last):
File "C:/Users/PIYU/PycharmProjects/PythonProgram/singleton.py", line 1, in <module>
class s:
File "C:/Users/PIYU/PycharmProjects/PythonProgram/singleton.py", line 4, in s
if s.__instance<2:
NameError: name 's' is not defined
The error is because you are trying to reference s in it's own definition, before it is actually defined. I would try using that condition in __init__ instead of before it.
In Python, class is an executable statement that creates a new class class object and bind it to the class name in the enclosing scope. Until the whole statement has been executed (IOW until the end of the class statement block), the class object doesn't exist and the name is not defined.
To make things clearer, this:
class Foo(object):
bar = 42
def foo(self):
print "foo"
is actually only syntactic sugar for
def foo(self):
print "foo"
Foo = type("Foo", (object,), {"foo": foo, "bar": 42})
del foo # remove the name from current scope
Related
class Difference:
def __init__(self, a):
self.__elements = a
def computeDifference(self):
b = min(self.__elements)
c = max(self.__elements)
result = abs(b-c)
self.maximumDifference = result
_ = input()
a = [int(e) for e in input().split(' ')]
d = Difference(a)
d.computeDifference()
print(d.maximumDifference)
I am unable to understand how I was able to call maximumdifference, which is a variable inside the computeDifference function, Which is inside the Difference class?
how I was able to call maximumdifference, which is a variable inside the computeDifference function, Which is inside the Difference class?
I think the core of your question comes from a slight misunderstanding: self.maximumDifference is a field in the class Difference. This field was created on-the-fly when the computeDifference function was called.
As another example:
... def foo(self):
... self.bar = "hi"
...
>>> a = A()
>>> a.bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'bar'
>>> a.foo()
>>> a.bar
'hi'
Here we can see how the bar attribute does not exist until after the foo function was run. If you're familiar with other languages, this may be surprising behavior --- many other languages require that class attributes/fields are fixed/specified in the class or constructor, but Python allows adding new fields on-the-fly.
I have the following python snippet:
class myClass:
myVar = 'a'
def __init__(self):
self.myOtherVar = 'b'
myVar = 'c' # Gets assigned but only as a local variable.
print myVar # prints 'a' !
print self.myOtherVar # says 'self' not found
My question is this;
What's the proper way to print the contents of myVar from within myClass and/or re-assign them from init?
The problem you are facing is because you don't understand how the scoping of class declarations work. A class declaration is executed in its own scope. After the execution is completed a new class object is created and the obtained scope is attached to the class as its __dict__.
Note: the class scope is not searched from within the methods scopes! This means that you have to reference class attributes as MyClass.attribute when inside a method definition.
For example:
class MyClass:
var = 1
# we are executing this code as a single block
# so you must reference the variable as is usual
print(var)
# default values are *not* inside the definition.
# they are evaluated in the outer scope, so use plain "var" here
def method(self, a_default=var):
print(a_default)
def other_method(self):
# inside methods you are in a different scope
print(MyClass.var)
# equivalent *if* no "var" instance attributes exists
print(self.var)
Note: since the class doesn't still exist when executing its declaration you cannot refer to MyClass at the "top level" of MyClass declaration:
class MyClass:
var = 1
print(MyClass.var) # error: MyClass still doesn't exist.
A side effect of this, is that the following code:
class MyClass:
x = 1
results = list(i+x for i in range(10))
Produces:
NameError Traceback (most recent call last)
<ipython-input-6-f1d4417b2e52> in <module>()
----> 1 class MyClass:
2 x = 1
3 results = list(i+x for i in range(10))
4
<ipython-input-6-f1d4417b2e52> in MyClass()
1 class MyClass:
2 x = 1
----> 3 results = list(i+x for i in range(10))
4
<ipython-input-6-f1d4417b2e52> in <genexpr>(.0)
1 class MyClass:
2 x = 1
----> 3 results = list(i+x for i in range(10))
4
NameError: name 'x' is not defined
Because generator expressions (and list-comprehensions in python3) are, in fact, considered functions with their own scope. Since the class scope isn't searched from inner function scopes the x cannot be found.
You can word around this using a function definition and default values:
class MyClass:
x = 1
def _make_results(x=x):
return list(i+x for i in range(10))
results = _make_results()
del _make_results # otherwise it would be added as a method.
# or:
results = (lambda x=x: list(i+x for i in range(10)))()
This isn't usually a problem since class definitions rarely contain anything other than method definitions and a few constants.
There are already a few questions on SO about class scopes:
The scope of names defined in class block doesn't extend to the methods' blocks. Why is that?
Short Description of the Scoping Rules?
Nested classes' scope?
Variable scopes in python classes
Why static binding works differently for class and function?
self.var will:
give var in self.__dict__ if present
give var in self.__class__.__dict__ if present
AttributeError
So use this or self.__class__.var if you want to access the static variable minding inheritance. If you extend myClass, the children instances will access the static variable in the child class.
If you want to access the static variable in myClass even when called from descendants, use myClass.var.
As for reassigning them, this must be done explicitly on the class object, or the assignment will just target the instance.
class myClass:
myVar = 'a'
def __init__(self):
self.myOtherVar = 'b'
print myVar # -> 'a'
class EmptyClass: pass
s = EmptyClass()
__init__(s)
myVar = s.myOtherVar
print myVar # -> 'b'
print myClass.myVar # -> 'b'
I'm trying clean implement of Objective-C's category in Python, and found this answer to similar question of mine. I copied the code below:
categories.py
class category(object):
def __init__(self, mainModule, override = True):
self.mainModule = mainModule
self.override = override
def __call__(self, function):
if self.override or function.__name__ not in dir(self.mainModule):
setattr(self.mainModule, function.__name__, function)
But I do not want to waste namespace.
By using this `categories', there remains a variable as NoneType object like below:
>>> from categories import category
>>> class Test(object):
... pass
...
>>> #category(Test)
... def foobar(self, msg):
... print msg
...
>>> test = Test()
>>> test.foobar('hello world')
hello world
>>> type(foobar)
<type 'NoneType'>
>>>
I want it to be like below
>>> from categories import category
>>> class Test(object):
... pass
...
>>> #category(Test)
... def foobar(self, msg):
... print msg
...
>>> test = Test()
>>> test.foobar('hello world')
hello world
>>> type(foobar)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'foobar' is not defined
>>>
Is there anyway to delete it automatically like below?
def __call__(self, function):
if self.override or function.__name__ not in dir(self.mainModule):
setattr(self.mainModule, function.__name__, function)
del(somewhere.function.__name__)
I found that sys._getframe give me some useful information. But I couldn't make it by myself.
No, there's no way to automatically do that. You would have to manually delete the name afterwards. category here is a decorator, which means that
#category(Test)
def f():
...
is the same as
def f():
...
f = category(Test)(f)
Even if, from inside category, you could delete the name in the outer scope, it wouldn't be enough, because that name is rebound after the decorator executes.
The code that you linked to borders on an abuse of the decorator syntax. Decorators are meant to provide a way to modify or extend the function they decorate, but that code relies on side-effects of the decorator (namely, assigning the function as a method of a class), and then discards the function. But it can only "discard" it by returning None, so None remains bound to the function's name, as you saw.
I would recommend you follow the advice of the highest-voted answer on that question, and simply assign new methods to your classes. There is no real need for an "infrastructure" like categories in Python, because you can just directly add new methods to existing classes whenever you want.
While I completely agree with what BrenBarn said, you could split the function removal into a later step. The problem is that after the decorator executed, the variable is reassigned. So you cannot perform the removal within the decorator itself.
You could however remember the functions and remove them from the module at a later point.
class category(object):
functions = []
def __init__(self, mainModule, override = True):
self.mainModule = mainModule
self.override = override
def __call__(self, function):
if self.override or function.__name__ not in dir(self.mainModule):
setattr(self.mainModule, function.__name__, function)
self.functions.append((inspect.getmodule(function), function.__name__))
return self.dummy
#staticmethod
def dummy():
pass
#classmethod
def cleanUp(cls):
for module, name in cls.functions:
if hasattr(module, name) and getattr(module, name) == cls.dummy:
delattr(module, name)
cls.functions = []
This category type will remember the functions it decorates and stores the names and modules they belong to for a later cleanup. The decorator also returns a special dummy function so that the cleanup can ensure that the variable was not reassigned later.
>>> class Test(object): pass
>>> #category(Test)
def foobar(self, msg):
print(msg)
>>> #category(Test)
def hello_world(self):
print('Hello world')
>>> test = Test()
>>> test.foobar('xy')
xy
>>> test.hello_world()
Hello world
>>> type(foobar)
<class 'function'>
>>> type(hello_world)
<class 'function'>
>>> category.cleanUp()
>>> type(foobar)
Traceback (most recent call last):
File "<pyshell#26>", line 1, in <module>
type(foobar)
NameError: name 'foobar' is not defined
>>> type(hello_world)
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
type(hello_world)
NameError: name 'hello_world' is not defined
I was wondering if anyone could explain and offer a solution to this issue:
$ cat object-override-methods.py
class A:
def foo(self):
return 1
class B:
def foo(self):
return 1
for klass in A, B:
orig_foo = klass.foo
def foo(self):
return orig_foo(self) * 2
klass.foo = foo
A().foo()
B().foo()
$ python object-override-methods.py
Traceback (most recent call last):
File "object-override-methods.py", line 15, in <module>
A().foo()
File "object-override-methods.py", line 12, in foo
return orig_foo(self) * 2
TypeError: unbound method foo() must be called with B instance as first argument (got A instance instead)
Thanks in advance.
orig_foo is a global variable which changes value with each pass through the loop. After the loop is done, orig_foo refers to B.foo.
The inner functions foo (one or each pass through the loop) both use the global value for orig_foo when they are called. So they both call B.foo(self).
When calling an "unbound method" like orig_foo, Python2 checks that the first argument is an instance of the appropriate class. A().foo() does not pass this check. (Interestingly, this check was removed in Python3, so there would be no TypeError raised, and this bug may become harder to find.)
To fix this, you must bind the value of orig_foo to the appropriate klass.
You can do that by making orig_foo a local variable of foo. One way to do that is to make orig_foo an argument of foo with a default value. Python binds default values at the time a function is defined. So orig_foo=orig_foo binds the local variable orig_foo to the current value of the klass.foo:
for klass in A, B:
orig_foo = klass.foo
def foo(self, orig_foo=orig_foo):
return orig_foo(self) * 2
klass.foo = foo
Because orig_foo is defined at global scope, you're trampling on its value each time round the loop. That trampled value is then shared by each of your new foo methods.
A simple fix is to move the code into a function, like this:
def rebind_foo(klass):
orig_foo = klass.foo
def foo(self):
return orig_foo(self) * 2
klass.foo = foo
for klass in A, B:
rebind_foo(klass)
That ensures that each new foo method gets its own value of orig_foo.
If I make a simple class like this:
class Foo:
i = 1
j = 2
Can I instantiate a new object by simply using Foo on the right-hand side ( as opposed to saying Foo() )? I would guess not, but I just tried the following and it worked:
finst = Foo
print finst.i
It works, because i is not a property of the object (or instance) but of the class. You are not creating a new instance.
Try:
class Foo:
def bar(self):
print 42
finst = Foo
finst.bar()
Traceback (most recent call last):
File "", line 1, in
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
You did not instantiate an object. You just defined a variable in class scope, and accessed it.
Foo by itself is the class object for class Foo:
>>> type(Foo)
<type 'classobj'>
>>> type(Foo())
<type 'instance'>
Your code:
finst = Foo
print finst.i
decodes as:
bind the name finst to the Foo class object.
print the value of the class' attribute i
That's because finst is merely an alias for the class Foo, and i and j are class variables, not instance variables. If you had declared them as instance variables:
class Foo:
def __init__(self):
self.i = 1
self.j = 2
Then your code would cause an error.
To answer your question, no, you must call a constructor to create an instance.