I'm a hack programmer -- no formal education. So, I don't know if this is technically a "factory", "abstract factory" or something else.
It is a way to generate a class dynamically, perhaps based on run-time data.
The point is that you can take a blank class object and dynamically add a constructor, class attributes, and instance methods. In principle, these could be configured dynamically in a program.
Since I don't know anything about programming theory, I welcome any criticism/discussion/suggestion. But, please be gentle!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | # create blank class
print "creating empty class object"
print
class A(object):
pass
# create hypothetical constructor
print "defining class constructor"
print "will set instance attribute \"a\""
print
def init(cls, a):
print "initializing the instance"
print
cls.__setattr__("a",a)
# create new method
print """\
defining method \"show\" that takes one argument, \
a class. It then prints class variable \"a\" and \
instance variable \"b\" \
"""
print
def show(cls):
print "received class", cls, "as first argument"
print "class attribute \"b\"", cls.b
print "instnace attribute \"a\":", cls.a
print
# add attribute to class
print "adding class attribute b=10"
print
A.b = 10
# add constructor to class
print "adding class constructor"
print "will set instance attribute \"a\""
print
A.__init__ = init
# add method to class
print "adding \"show\" method to class"
print
A.show = show
# create instance
print "creating instance \"q\" and passing \"5\" to constructor"
print
q = A(5)
# check class attribute
print "checking class attribute \"b\""
print "should equal 10"
print q.b
print
# check instance attribute
print "checking instance attribute \"a\""
print "should equal 5"
print q.a
print
# test instance method
print "testing method \"show\""
print
q.show()
# change class attribute
print "now chaning class attribute \"b\" to 30"
print
A.b = 30
# check reference to class attribute
print "checking that the class attribute changed"
print
q.show()
|
First we create an empty class. Then we create a function to be the constructor. We define it to take two arguments. However, because we (dynamically) bind it to the class, when an instance calls it, the instance is passed as the first argument.
Next we define a free method, also taking two arguments. Likewise, when bound to the class, the instance passes itself as the first argument.
Next, we demonstrate that this all works. And finally we show that we can change a class attribute, and this passes to the instance.
I hope someone finds this useful!
Welcome to dynamic languages! Yes, you got the terminology wrong in some places.
The init function takes an instance as its first parameter, not a class, so I'd use
self
instead. Also, __special__ methods like __setattr__ are not supposed (normally) to be called explicitely; usesetattr(self, "a", a)
instead. And, since the attribute name is constant, it's always written asself.a = a
(more legible, and faster).Same with
show
: takes an instance, not a class, as argument.And what's a "free method"? If you're talking about show(), it is a function and takes one argument, not two.
To condense your example in a few lines, there are several ways to define a class:
Method 1, traditional:
Method 2, empty class, then adding required pieces:
Method 3, using
type
:All these ways create the same class A, which can be used as follows: