I have defined a class to process a file but get the following error when I try to instantiate the class and pass the filename.
Let me know what would be the problem?
>>> class fileprocess:
... def pread(self,filename):
... print filename
... f = open(filename,'w')
... print f
>>> x = fileprocess
>>> x.pread('c:/test.txt')
Traceback (most recent call last):
File "", line 1, in
TypeError: unbound method pread() must be called with
fileprocess instance as first argument (got nothing instead)
x = fileprocess does not mean x is an instance of fileprocess. It means x is now an alias for the fileprocess class.
You need to create an instance, using the ().
x = fileprocess()
x.pread('c:/test.txt')
In addition, based on your original code, you could use x to create class instances.
x = fileprocess
f = x() # creates a fileprocess
f.pread('c:/test.txt')
x = fileprocess should be x = fileprocess()
Currently x is referring to the class itself, not an instance of the class. So when you call x.pread('c:/test.txt') that's the same as calling fileprocess.pread('c:/test.txt')
But why use write mode for read function? Maybe it's pwrite?
Related
If I define the __iter__ method as follows, it won't work:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
for i in A().__iter__():
print(i)
iter(A())
Result:
t
e
x
t
Traceback (most recent call last):
File "...\mytest.py", line 10, in <module>
iter(A())
TypeError: 'A' object is not iterable
As you can see, calling A().__iter__() works, but A() is not iterable.
However if I define __iter__ for the class, then it will work:
class A:
def __init__(self):
self.__class__.__iter__ = staticmethod(lambda: iter('text'))
# or:
# self.__class__.__iter__ = lambda s: iter('text')
for i in A():
print(i)
iter(A())
# will print:
# t
# e
# x
# t
Does anyone know why python has been designed like this? i.e. why __iter__ as instance variable does not work? Don't you find it unintuitive?
It is done by design. You can find the thorough description here: https://docs.python.org/3/reference/datamodel.html#special-method-lookup
Short answer: the special method must be set on the class object itself in order to be consistently invoked by the interpreter.
Long answer: the idea behind this is to speed up well-known constructions. In your example:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
How often are you going to write a code like this in real life? So, what Python does - it skips a dictionary lookup of the instance, i.e. iter(A()) simply does not "see" that self.__iter__, which is actually self.__dict__['__iter__'] in this case.
It also skips all the __getattribute__ instance and metaclass lookup gaining a significant speedup.
Are there any shortcuts for defining an empty object in Python or do you always have to create an instance of a custom empty class?
Edit: I mean an empty object usable for duck typing.
Yes, in Python 3.3 SimpleNamespace was added
Unlike object, with SimpleNamespace you can add and remove attributes. If a SimpleNamespace object is initialized with keyword arguments, those are directly added to the underlying namespace.
Example:
import types
x = types.SimpleNamespace()
x.happy = True
print(x.happy) # True
del x.happy
print(x.happy) # AttributeError. object has no attribute 'happy'
You can use type to create a new class on the fly and then instantiate it. Like so:
>>> t = type('test', (object,), {})()
>>> t
<__main__.test at 0xb615930c>
The arguments to type are: Class name, a tuple of base classes, and the object's dictionary. Which can contain functions (the object's methods) or attributes.
You can actually shorten the first line to
>>> t = type('test', (), {})()
>>> t.__class__.__bases__
(object,)
Because by default type creates new style classes that inherit from object.
type is used in Python for metaprogramming.
But if you just want to create an instance of object. Then, just create an instance of it. Like lejlot suggests.
Creating an instance of a new class like this has an important difference that may be useful.
>>> a = object()
>>> a.whoops = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'whoops'
Where as:
>>> b = type('', (), {})()
>>> b.this_works = 'cool'
>>>
One simple, less-terrifying-looking way to create an empty(-ish) object is to exploit the fact that functions are objects in Python, including Lambda Functions:
obj = lambda: None
obj.test = "Hello, world!"
For example:
In [18]: x = lambda: None
In [19]: x.test = "Hello, world!"
In [20]: x.test
Out[20]: 'Hello, world!'
You said it in the question, but as no answer mentioned it with code, this is probably one of the cleanest solutions:
class Myobject:
pass
x = Myobject()
x.test = "Hello, world!" # working
What do you mean by "empty object"? Instance of class object? You can simply run
a = object()
or maybe you mean initialization to the null reference? Then you can use
a = None
All the proposed solutions are somewhat awkward.
I found a way that is not hacky but is actually according to the original design.
>>> from mock import Mock
>>> foo = Mock(spec=['foo'], foo='foo')
>>> foo.foo
'foo'
>>> foo.bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../virtualenv/local/lib/python2.7/site-packages/mock/mock.py", line 698, in __getattr__
raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'bar'
See the documentation of unittest.mock here.
You can use
x = lambda: [p for p in x.__dict__.keys()]
Then
x.p1 = 2
x.p2 = "Another property"
After
x()
# gives
# ['p1', 'p2']
And
[(p, getattr(x,p)) for p in x()]
# gives
# [('p1', 2), ('p2', 'Another property')]
Constructs a new empty Set object. If the optional iterable parameter is supplied, updates the set with elements obtained from iteration. All of the elements in iterable should be immutable or be transformable to an immutable using the protocol described in section Protocol for automatic conversion to immutable.
Ex:
myobj = set()
for i in range(1,10): myobj.add(i)
print(myobj)
In my opinion, the easiest way is:
def x():pass
x.test = 'Hello, world!'
If there is a desired type of the empty object, in other words, you want to create it but don't call the __init__ initializer, you can use __new__:
class String(object):
...
uninitialized_empty_string = String.__new__(String)
Source: https://stackoverflow.com/a/2169191/6639500.
In the following code ;
>>> class fooo():
def __init__(self):
self.a=[]
>>> fooo().a
[]
>>> fooo.a
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
fooo.a
AttributeError: class fooo has no attribute 'a'
i'm a little confuse about the notations fooo().a and fooo.a for accessing the variable "a".Is it that whenever we use fooo().a a object of fooo() class is thrown and it is equivalent to doing as:
>>> m=fooo()
>>> m.a
[]
; while using the notation fooo.a , we are expecting a to be a class/static variable ? Is i'm right or it is something else?
a is an instance attribute. It can be accessed using fooo().a. But note that doing that just throws away the fooo instance created; a more sensible example is:
y = fooo()
y.a = 5
It doesn't exist until an instance of the class is created. Yeah you are totally correct.
I a new learner for python program, and I confuse with creating class instance as following, what are they different?
Class declaration:
class TestClass:
def __init__(self, one=10, two=20, three=30):
self.one = one
self.two = two
self.three = three
1st. (worng)
x = TestClass
print x
print x(50)
print x.one, x.two
output:
__main__.TestClass
<__main__.TestClass instance at 0x0000000002445208>
Traceback (most recent call last):
File "D:\workspace-QATool_vNext\testStudyCode\test\StudyCode.py", line 27, in <module>
print x.one, x.two
AttributeError: class TestClass has no attribute 'one'
2nd. (correct)
y = TestClass()
print y
print y.one, y.two
output:
<__main__.TestClass instance at 0x00000000023B5208>
10 20
The first one gives you a pointer to a class object (yes, these are also objects), the second one an instance to a object.
__init__ is only called when you create a new instance of an object. This is what the () after the class do: create a new instance.
You could make your first example work by doing it like this:
x = TestClass #'x' points to class object
print x
z = x(50) #'x' still points to class object but 'z' points to new instance
print z
print z.one, z.two #and 'z' is now usable as a new instance
print x.one #where 'x' still points to the class object that does not know 'one' since it hasn't run '__init__'
The problem was that x still pointed to the class object intead of the newly created instance.
The Function init is the constructor for the class and it is not called untill you use following syntex:
y = TestClass()
With that the object of TestClass (i.e. y) has all attributes.
In your first example, you are simply copying the class onto x. You are not creating an instance at all, and thus, the __init__ constructor does not run. print x(50) is what is making an instance of the class, because you are actually calling the class. But you have not stored it anywhere, so it is pointless.
In the second one, you are creating an instance (note the paretheses after TestClass), and thus accessing the variables work as you have discovered
There is a very subtle difference between your two attempts to create and use a TestClass-object.
x = TestClass
This copies the class TestClass to x.
y = TestClass()
This creates an instance of testclass and assigns it to y.
y = x()
By copying the testclass to x, x contains the exact same class and can therefore also be used to initiate objects of the class testclass.
Most people will probably say this is a bad idea. I want to use the content of a string as the name of a variable. I want to accomplish the dreaded:
s = 'x'
x = 1
where the variable name x comes (somehow?) from the string s.
To answer the "why?", say I have a global default value for x that I want the option of overriding in a function. But:
x = 0
def f(**kw):
print x
f(x=1)
prints 0 not 1. If I could use the strings in kw.keys() to reassign x (or any other globally set variables) then I'd be happy.
I realize that this works for reassigning x in f:
x = 0
def f(x=x):
print x
f(x=1)
But I want to do this for cases where there are MANY variables in my namespace that I might at some point want to override without rewriting every function definition in my module.
Check out exec
>>> print x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> s = 'x'
>>> exec(s + " = 1")
>>> print x
1
See also: How can I assign the value of a variable using eval in python?
After a little experimentation, this also seems to work:
>>> print x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> s = 'x'
>>> globals()[s] = 1
>>> print x
1
You should reconsider using the global keyword (http://docs.python.org/2.7/reference/simple_stmts.html#the-global-statement)
I recommend taking a look at Use of "global" keyword in Python as well.
Also, as promanow suggested, using a global mutable object might be a better approach.
However, keep in mind that having large amounts of code that might modify or depend on a mutating global is very scary idea, from a maintenance perspective. Tread carefully.
Assignment via function arguments is not obvious and therefore is not considered Pythonic (Python is not C). See import this.
The cheap way that I've done flat configuration is through a global partial dict:
In [1]: from functools import partial
In [2]: config = partial(dict)
In [3]: def f(x=None):
...: print x or config.x
...:
In [4]: config.x = 'foo'
In [5]: f()
foo
Something to this effect is obvious, readable and therefore much more maintainable.
But I want to do this for cases where there are MANY variables in my namespace that I might at some point want to override without rewriting every function definition in my module.
It sounds like you want a class:
class Foo(object):
x = 0
def f(self):
print self.x
my_foo = Foo()
my_foo.x = 1
my_foo.f()
I use the following for creating dynamically custom modeling databses for targets of interest from one global database:
DBs = ["Target_1_DB","Target_2_DB","Target_3_DB"]
for db in DBs:
print(db)
exec_str = "Modeling_DB_Base = " + db
exec(exec_str)
#s = "Modeling_DB_Base"
#globals()[s] = db
print(Modeling_DB_Base.shape)
using the commented-out globals() results in error message: AttributeError: 'str' object has no attribute 'shape'
You can use the following solution:
s = 'x'
locals()[s] = 1