update from Atlas
This commit is contained in:
48
metaprog/blackknight.py
Normal file
48
metaprog/blackknight.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
This class is inspired by the Black Knight scene in the movie
|
||||
"Monty Python and the Holy Grail", where King Arthur fights the
|
||||
Black Knight, slicing off his arms and legs, but the knight
|
||||
refuses to concede defeat.
|
||||
|
||||
# BEGIN BLACK_KNIGHT_DEMO
|
||||
>>> knight = BlackKnight()
|
||||
>>> knight.member
|
||||
next member is:
|
||||
'an arm'
|
||||
>>> del knight.member
|
||||
BLACK KNIGHT (loses an arm)
|
||||
-- 'Tis but a scratch.
|
||||
>>> del knight.member
|
||||
BLACK KNIGHT (loses another arm)
|
||||
-- It's just a flesh wound.
|
||||
>>> del knight.member
|
||||
BLACK KNIGHT (loses a leg)
|
||||
-- I'm invincible!
|
||||
>>> del knight.member
|
||||
BLACK KNIGHT (loses another leg)
|
||||
-- All right, we'll call it a draw.
|
||||
|
||||
# END BLACK_KNIGHT_DEMO
|
||||
"""
|
||||
|
||||
# BEGIN BLACK_KNIGHT
|
||||
class BlackKnight:
|
||||
|
||||
def __init__(self):
|
||||
self.members = ['an arm', 'another arm',
|
||||
'a leg', 'another leg']
|
||||
self.phrases = ["'Tis but a scratch.",
|
||||
"It's just a flesh wound.",
|
||||
"I'm invincible!",
|
||||
"All right, we'll call it a draw."]
|
||||
|
||||
@property
|
||||
def member(self):
|
||||
print('next member is:')
|
||||
return self.members[0]
|
||||
|
||||
@member.deleter
|
||||
def member(self):
|
||||
text = 'BLACK KNIGHT (loses {})\n-- {}'
|
||||
print(text.format(self.members.pop(0), self.phrases.pop(0)))
|
||||
# END BLACK_KNIGHT
|
||||
23
metaprog/doc_property.py
Normal file
23
metaprog/doc_property.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
Example of property documentation
|
||||
|
||||
>>> f = Foo()
|
||||
>>> f.bar = 77
|
||||
>>> f.bar
|
||||
77
|
||||
>>> Foo.bar.__doc__
|
||||
'The bar attribute'
|
||||
"""
|
||||
|
||||
# BEGIN DOC_PROPERTY
|
||||
class Foo:
|
||||
|
||||
@property
|
||||
def bar(self):
|
||||
'''The bar attribute'''
|
||||
return self.__dict__['bar']
|
||||
|
||||
@bar.setter
|
||||
def bar(self, value):
|
||||
self.__dict__['bar'] = value
|
||||
# END DOC_PROPERTY
|
||||
@@ -1,30 +1,30 @@
|
||||
"""
|
||||
explore1.py: Script to explore the OSCON schedule feed
|
||||
|
||||
# BEGIN EXPLORE1_DEMO
|
||||
>>> from osconfeed import load
|
||||
>>> raw_feed = load()
|
||||
>>> feed = FrozenJSON(raw_feed)
|
||||
>>> sorted(feed.Schedule.keys())
|
||||
>>> feed = FrozenJSON(raw_feed) # <1>
|
||||
>>> len(feed.Schedule.speakers) # <2>
|
||||
357
|
||||
>>> sorted(feed.Schedule.keys()) # <3>
|
||||
['conferences', 'events', 'speakers', 'venues']
|
||||
>>> for key, value in sorted(feed.Schedule.items()):
|
||||
... print('{:3} {}'.format(len(value), key))
|
||||
...
|
||||
1 conferences
|
||||
484 events
|
||||
357 speakers
|
||||
53 venues
|
||||
>>> feed.Schedule.speakers[-1].name
|
||||
>>> feed.Schedule.speakers[-1].name # <4>
|
||||
'Carina C. Zona'
|
||||
>>> carina = feed.Schedule.speakers[-1]
|
||||
>>> carina.twitter
|
||||
'cczona'
|
||||
>>> feed.Schedule.events[40].name
|
||||
>>> talk = feed.Schedule.events[40] # <5>
|
||||
>>> talk.name
|
||||
'There *Will* Be Bugs'
|
||||
>>> feed.Schedule.events[40].speakers
|
||||
>>> talk.speakers # <6>
|
||||
[3471, 5199]
|
||||
>>> talk.flavor # <7>
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'flavor'
|
||||
|
||||
# END EXPLORE1_DEMO
|
||||
"""
|
||||
|
||||
# BEGIN EXPLORE1
|
||||
from collections import abc
|
||||
|
||||
|
||||
@@ -34,19 +34,20 @@ class FrozenJSON:
|
||||
"""
|
||||
|
||||
def __init__(self, mapping):
|
||||
self._data = dict(mapping)
|
||||
self._data = dict(mapping) # <1>
|
||||
|
||||
def __getattr__(self, name):
|
||||
def __getattr__(self, name): # <2>
|
||||
if hasattr(self._data, name):
|
||||
return getattr(self._data, name)
|
||||
return getattr(self._data, name) # <3>
|
||||
else:
|
||||
return FrozenJSON.build(self._data[name])
|
||||
return FrozenJSON.build(self._data[name]) # <4>
|
||||
|
||||
@classmethod
|
||||
def build(cls, obj):
|
||||
if isinstance(obj, abc.Mapping):
|
||||
def build(cls, obj): # <5>
|
||||
if isinstance(obj, abc.Mapping): # <6>
|
||||
return cls(obj)
|
||||
elif isinstance(obj, abc.MutableSequence):
|
||||
elif isinstance(obj, abc.MutableSequence): # <7>
|
||||
return [cls.build(item) for item in obj]
|
||||
else:
|
||||
else: # <8>
|
||||
return obj
|
||||
# END EXPLORE1
|
||||
|
||||
@@ -4,27 +4,25 @@ explore2.py: Script to explore the OSCON schedule feed
|
||||
>>> from osconfeed import load
|
||||
>>> raw_feed = load()
|
||||
>>> feed = FrozenJSON(raw_feed)
|
||||
>>> len(feed.Schedule.speakers)
|
||||
357
|
||||
>>> sorted(feed.Schedule.keys())
|
||||
['conferences', 'events', 'speakers', 'venues']
|
||||
>>> for key, value in sorted(feed.Schedule.items()):
|
||||
... print('{:3} {}'.format(len(value), key))
|
||||
...
|
||||
1 conferences
|
||||
484 events
|
||||
357 speakers
|
||||
53 venues
|
||||
>>> feed.Schedule.speakers[-1].name
|
||||
'Carina C. Zona'
|
||||
>>> carina = feed.Schedule.speakers[-1]
|
||||
>>> carina.twitter
|
||||
'cczona'
|
||||
>>> feed.Schedule.events[40].name
|
||||
>>> talk = feed.Schedule.events[40]
|
||||
>>> talk.name
|
||||
'There *Will* Be Bugs'
|
||||
>>> feed.Schedule.events[40].speakers
|
||||
>>> talk.speakers
|
||||
[3471, 5199]
|
||||
>>> talk.flavor
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'flavor'
|
||||
|
||||
"""
|
||||
|
||||
# BEGIN EXPLORE2
|
||||
from collections import abc
|
||||
|
||||
|
||||
@@ -33,11 +31,11 @@ class FrozenJSON:
|
||||
using attribute notation
|
||||
"""
|
||||
|
||||
def __new__(cls, arg):
|
||||
def __new__(cls, arg): # <1>
|
||||
if isinstance(arg, abc.Mapping):
|
||||
return super().__new__(cls)
|
||||
elif isinstance(arg, abc.MutableSequence):
|
||||
return [FrozenJSON(item) for item in arg]
|
||||
return super().__new__(cls) # <2>
|
||||
elif isinstance(arg, abc.MutableSequence): # <3>
|
||||
return [cls(item) for item in arg]
|
||||
else:
|
||||
return arg
|
||||
|
||||
@@ -48,4 +46,5 @@ class FrozenJSON:
|
||||
if hasattr(self._data, name):
|
||||
return getattr(self._data, name)
|
||||
else:
|
||||
return FrozenJSON(self._data[name])
|
||||
return FrozenJSON(self._data[name]) # <4>
|
||||
# END EXPLORE2
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
{ "conferences": [{"serial": 115 }],
|
||||
"events": [
|
||||
{ "serial": 34505,
|
||||
"name": "Why Schools Don't Use Open Source to Teach Programming",
|
||||
"name": "Why Schools Don´t Use Open Source to Teach Programming",
|
||||
"event_type": "40-minute conference session",
|
||||
"time_start": "2014-07-23 11:30:00",
|
||||
"time_stop": "2014-07-23 12:10:00",
|
||||
"venue_serial": 1462,
|
||||
"description": "Aside from the fact that high school programming curricula often require proprietary IDEs, they also don't involve examining any source code from Open Source software projects. What changes would be required in programming curricula to incorporate Open Source? And is that a desirable objective?",
|
||||
"description": "Aside from the fact that high school programming...",
|
||||
"website_url": "http://oscon.com/oscon2014/public/schedule/detail/34505",
|
||||
"speakers": [157509],
|
||||
"categories": ["Education"] }
|
||||
@@ -20,7 +20,7 @@
|
||||
"position": "CTO",
|
||||
"affiliation": "Sharewave",
|
||||
"twitter": "sharewaveteam",
|
||||
"bio": "Robert 'r0ml' Lefkowitz is the CTO at Sharewave, a startup building an investor management portal. This year, he was a resident at the winter session of Hacker School. He is a Distinguished Engineer of the ACM." }
|
||||
"bio": "Robert ´r0ml´ Lefkowitz is the CTO at Sharewave, a startup..." }
|
||||
],
|
||||
"venues": [
|
||||
{ "serial": 1462,
|
||||
|
||||
@@ -1,43 +1,49 @@
|
||||
"""
|
||||
osconfeed.py: Script to download the OSCON schedule feed
|
||||
|
||||
>>> feed = load()
|
||||
>>> sorted(feed['Schedule'].keys())
|
||||
# BEGIN OSCONFEED_DEMO
|
||||
|
||||
>>> feed = load() # <1>
|
||||
>>> sorted(feed['Schedule'].keys()) # <2>
|
||||
['conferences', 'events', 'speakers', 'venues']
|
||||
>>> for key, value in sorted(feed['Schedule'].items()):
|
||||
... print('{:3} {}'.format(len(value), key))
|
||||
... print('{:3} {}'.format(len(value), key)) # <3>
|
||||
...
|
||||
1 conferences
|
||||
484 events
|
||||
357 speakers
|
||||
53 venues
|
||||
>>> feed['Schedule']['speakers'][-1]['name']
|
||||
>>> feed['Schedule']['speakers'][-1]['name'] # <4>
|
||||
'Carina C. Zona'
|
||||
>>> carina = feed['Schedule']['speakers'][-1]
|
||||
>>> carina['twitter']
|
||||
'cczona'
|
||||
>>> feed['Schedule']['speakers'][-1]['serial'] # <5>
|
||||
141590
|
||||
>>> feed['Schedule']['events'][40]['name']
|
||||
'There *Will* Be Bugs'
|
||||
>>> feed['Schedule']['events'][40]['speakers']
|
||||
>>> feed['Schedule']['events'][40]['speakers'] # <6>
|
||||
[3471, 5199]
|
||||
|
||||
|
||||
# END OSCONFEED_DEMO
|
||||
"""
|
||||
|
||||
# BEGIN OSCONFEED
|
||||
from urllib.request import urlopen
|
||||
import warnings
|
||||
import os
|
||||
import json
|
||||
|
||||
URL = 'http://www.oreilly.com/pub/sc/osconfeed'
|
||||
JSON_NAME = 'data/osconfeed.json'
|
||||
JSON = 'data/osconfeed.json'
|
||||
|
||||
|
||||
def load():
|
||||
if not os.path.exists(JSON_NAME):
|
||||
msg = 'downloading {} to {}'.format(URL, JSON_NAME)
|
||||
warnings.warn(msg)
|
||||
with urlopen(URL) as remote, open(JSON_NAME, 'wb') as local:
|
||||
if not os.path.exists(JSON):
|
||||
msg = 'downloading {} to {}'.format(URL, JSON)
|
||||
warnings.warn(msg) # <1>
|
||||
with urlopen(URL) as remote, open(JSON, 'wb') as local: # <2>
|
||||
local.write(remote.read())
|
||||
|
||||
with open(JSON_NAME) as fp:
|
||||
return json.load(fp)
|
||||
with open(JSON) as fp:
|
||||
return json.load(fp) # <3>
|
||||
|
||||
# END OSCONFEED
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
"""
|
||||
schedule1.py: traversing OSCON schedule data
|
||||
|
||||
# BEGIN SCHEDULE1_DEMO
|
||||
>>> import shelve
|
||||
>>> db = shelve.open(DB_NAME)
|
||||
>>> if CONFERENCE not in db: load_db(db)
|
||||
>>> event = db['event.33950']
|
||||
>>> speaker = db['speaker.3471']
|
||||
>>> speaker.name
|
||||
>>> db = shelve.open(DB_NAME) # <1>
|
||||
>>> if CONFERENCE not in db: # <2>
|
||||
... load_db(db) # <3>
|
||||
...
|
||||
>>> speaker = db['speaker.3471'] # <4>
|
||||
>>> type(speaker) # <5>
|
||||
<class 'schedule1.Record'>
|
||||
>>> speaker.name # <6>
|
||||
'Anna Martelli Ravenscroft'
|
||||
>>> speaker.twitter
|
||||
'annaraven'
|
||||
>>> db.close()
|
||||
>>> db.close() # <7>
|
||||
|
||||
# END SCHEDULE1_DEMO
|
||||
|
||||
"""
|
||||
|
||||
# BEGIN SCHEDULE1
|
||||
import warnings
|
||||
|
||||
import osconfeed
|
||||
@@ -23,15 +30,18 @@ CONFERENCE = 'conference.115'
|
||||
|
||||
|
||||
class Record:
|
||||
def __init__(self, mapping):
|
||||
self.__dict__.update(mapping)
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs) # <1>
|
||||
|
||||
|
||||
def load_db(db):
|
||||
raw_data = osconfeed.load()
|
||||
raw_data = osconfeed.load() # <2>
|
||||
warnings.warn('loading ' + DB_NAME)
|
||||
for collection, rec_list in raw_data['Schedule'].items():
|
||||
rec_type = collection[:-1]
|
||||
for fields in rec_list:
|
||||
key = '{}.{}'.format(rec_type, fields['serial'])
|
||||
db[key] = Record(fields)
|
||||
for collection, rec_list in raw_data['Schedule'].items(): # <3>
|
||||
record_type = collection[:-1] # <4>
|
||||
for record in rec_list:
|
||||
key = '{}.{}'.format(record_type, record['serial']) # <5>
|
||||
record['serial'] = key # <6>
|
||||
db[key] = Record(**record) # <7>
|
||||
|
||||
# END SCHEDULE1
|
||||
|
||||
@@ -4,82 +4,128 @@ schedule2.py: traversing OSCON schedule data
|
||||
>>> import shelve
|
||||
>>> db = shelve.open(DB_NAME)
|
||||
>>> if CONFERENCE not in db: load_db(db)
|
||||
>>> DbRecord.set_db(db)
|
||||
>>> event = Event.get('event.33950')
|
||||
>>> event
|
||||
|
||||
# BEGIN SCHEDULE2_DEMO
|
||||
|
||||
>>> DbRecord.set_db(db) # <1>
|
||||
>>> event = DbRecord.fetch('event.33950') # <2>
|
||||
>>> event # <3>
|
||||
<Event 'There *Will* Be Bugs'>
|
||||
>>> event.speakers[0].name
|
||||
'Anna Martelli Ravenscroft'
|
||||
>>> event.venue # <4>
|
||||
<DbRecord serial='venue.1449'>
|
||||
>>> event.venue.name # <5>
|
||||
'Portland 251'
|
||||
>>> for spkr in event.speakers: # <6>
|
||||
... print('{0.serial}: {0.name}'.format(spkr))
|
||||
...
|
||||
speaker.3471: Anna Martelli Ravenscroft
|
||||
speaker.5199: Alex Martelli
|
||||
|
||||
# END SCHEDULE2_DEMO
|
||||
|
||||
>>> db.close()
|
||||
|
||||
"""
|
||||
|
||||
# BEGIN SCHEDULE2_RECORD
|
||||
import warnings
|
||||
import inspect
|
||||
import inspect # <1>
|
||||
|
||||
import osconfeed
|
||||
|
||||
DB_NAME = 'data/schedule2_db'
|
||||
DB_NAME = 'data/schedule2_db' # <2>
|
||||
CONFERENCE = 'conference.115'
|
||||
|
||||
|
||||
class Record:
|
||||
def __init__(self, mapping):
|
||||
self.__dict__.update(mapping)
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
def __eq__(self, other):
|
||||
def __eq__(self, other): # <3>
|
||||
if isinstance(other, Record):
|
||||
return self.__dict__ == other.__dict__
|
||||
else:
|
||||
return NotImplemented
|
||||
# END SCHEDULE2_RECORD
|
||||
|
||||
|
||||
# BEGIN SCHEDULE2_DBRECORD
|
||||
class MissingDatabaseError(RuntimeError):
|
||||
"""Raised when a database is required but was not set.""" # <1>
|
||||
|
||||
|
||||
class DbRecord(Record): # <2>
|
||||
|
||||
_db = None # <3>
|
||||
|
||||
@staticmethod # <4>
|
||||
def set_db(db):
|
||||
DbRecord._db = db # <5>
|
||||
|
||||
@staticmethod # <6>
|
||||
def get_db():
|
||||
return DbRecord._db
|
||||
|
||||
@classmethod # <7>
|
||||
def fetch(cls, ident):
|
||||
db = cls.get_db()
|
||||
try:
|
||||
return db[ident] # <8>
|
||||
except TypeError:
|
||||
if db is None: # <9>
|
||||
msg = "database not set; call '{}.set_db(my_db)'"
|
||||
raise MissingDatabaseError(msg.format(cls.__name__))
|
||||
else: # <10>
|
||||
raise
|
||||
|
||||
def __repr__(self):
|
||||
if hasattr(self, 'name'):
|
||||
ident = repr(self.name)
|
||||
if hasattr(self, 'serial'): # <11>
|
||||
cls_name = self.__class__.__name__
|
||||
return '<{} serial={!r}>'.format(cls_name, self.serial)
|
||||
else:
|
||||
ident = 'object at ' + hex(id(self))
|
||||
cls_name = self.__class__.__name__
|
||||
return '<{} {}>'.format(cls_name, ident)
|
||||
return super().__repr__() # <12>
|
||||
# END SCHEDULE2_DBRECORD
|
||||
|
||||
|
||||
class DbRecord(Record):
|
||||
|
||||
@classmethod
|
||||
def set_db(cls, db):
|
||||
cls._db = db
|
||||
|
||||
@classmethod
|
||||
def get(cls, ident):
|
||||
return cls._db[ident]
|
||||
|
||||
|
||||
class Event(DbRecord):
|
||||
# BEGIN SCHEDULE2_EVENT
|
||||
class Event(DbRecord): # <1>
|
||||
|
||||
@property
|
||||
def venue(self):
|
||||
key = self.venue_serial
|
||||
return self._db['venue.{}'.format(key)]
|
||||
key = 'venue.{}'.format(self.venue_serial)
|
||||
return self.fetch(key) # <2>
|
||||
|
||||
@property
|
||||
def speakers(self):
|
||||
spkr_serials = self.__dict__['speakers']
|
||||
if not hasattr(self, '_speaker_refs'):
|
||||
self._speaker_refs = [self._db['speaker.{}'.format(key)]
|
||||
for key in spkr_serials]
|
||||
return self._speaker_refs
|
||||
if not hasattr(self, '_speaker_objs'): # <3>
|
||||
spkr_serials = self.__dict__['speakers'] # <4>
|
||||
self._speaker_objs = [self.fetch('speaker.{}'.format(key))
|
||||
for key in spkr_serials] # <5>
|
||||
return self._speaker_objs # <6>
|
||||
|
||||
def __repr__(self):
|
||||
if hasattr(self, 'name'): # <7>
|
||||
cls_name = self.__class__.__name__
|
||||
return '<{} {!r}>'.format(cls_name, self.name)
|
||||
else:
|
||||
return super().__repr__() # <8>
|
||||
# END SCHEDULE2_EVENT
|
||||
|
||||
|
||||
# BEGIN SCHEDULE2_LOAD
|
||||
def load_db(db):
|
||||
raw_data = osconfeed.load()
|
||||
warnings.warn('loading ' + DB_NAME)
|
||||
for collection, rec_list in raw_data['Schedule'].items():
|
||||
rec_type = collection[:-1]
|
||||
for fields in rec_list:
|
||||
cls_name = rec_type.capitalize()
|
||||
cls = globals().get(cls_name, Record)
|
||||
if inspect.isclass(cls) and issubclass(cls, Record):
|
||||
record = cls(fields)
|
||||
else:
|
||||
Record(fields)
|
||||
key = '{}.{}'.format(rec_type, fields['serial'])
|
||||
db[key] = record
|
||||
record_type = collection[:-1] # <1>
|
||||
cls_name = record_type.capitalize() # <2>
|
||||
cls = globals().get(cls_name, DbRecord) # <3>
|
||||
if inspect.isclass(cls) and issubclass(cls, DbRecord): # <4>
|
||||
factory = cls # <5>
|
||||
else:
|
||||
factory = DbRecord # <6>
|
||||
for record in rec_list: # <7>
|
||||
key = '{}.{}'.format(record_type, record['serial'])
|
||||
record['serial'] = key
|
||||
db[key] = factory(**record) # <>
|
||||
# END SCHEDULE2_LOAD
|
||||
|
||||
@@ -13,7 +13,7 @@ def db():
|
||||
|
||||
|
||||
def test_record_class():
|
||||
rec = schedule.Record({'spam': 99, 'eggs': 12})
|
||||
rec = schedule.Record(spam=99, eggs=12)
|
||||
assert rec.spam == 99
|
||||
assert rec.eggs == 12
|
||||
|
||||
|
||||
@@ -13,16 +13,16 @@ def db():
|
||||
|
||||
|
||||
def test_record_attr_access():
|
||||
rec = schedule.Record({'spam': 99, 'eggs': 12})
|
||||
rec = schedule.Record(spam=99, eggs=12)
|
||||
assert rec.spam == 99
|
||||
assert rec.eggs == 12
|
||||
|
||||
|
||||
def test_record_repr():
|
||||
rec = schedule.Record({'spam': 99, 'eggs': 12})
|
||||
assert repr(rec).startswith('<Record object at 0x')
|
||||
rec2 = schedule.Record({'name': 'Fido'})
|
||||
assert repr(rec2) == "<Record 'Fido'>"
|
||||
rec = schedule.DbRecord(spam=99, eggs=12)
|
||||
assert 'DbRecord object at 0x' in repr(rec)
|
||||
rec2 = schedule.DbRecord(serial=13)
|
||||
assert repr(rec2) == "<DbRecord serial=13>"
|
||||
|
||||
|
||||
def test_conference_record(db):
|
||||
@@ -34,9 +34,14 @@ def test_speaker_record(db):
|
||||
assert speaker.name == 'Anna Martelli Ravenscroft'
|
||||
|
||||
|
||||
def test_missing_db_exception():
|
||||
with pytest.raises(schedule.MissingDatabaseError):
|
||||
schedule.DbRecord.fetch('venue.1585')
|
||||
|
||||
|
||||
def test_dbrecord(db):
|
||||
schedule.DbRecord.set_db(db)
|
||||
venue = schedule.DbRecord.get('venue.1585')
|
||||
venue = schedule.DbRecord.fetch('venue.1585')
|
||||
assert venue.name == 'Exhibit Hall B'
|
||||
|
||||
|
||||
|
||||
10
metaprog/pseudo_construction.py
Normal file
10
metaprog/pseudo_construction.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# pseudo-code for object construction
|
||||
def object_maker(the_class, some_arg):
|
||||
new_object = the_class.__new__(some_arg)
|
||||
if isinstance(new_object, the_class):
|
||||
the_class.__init__(new_object, some_arg)
|
||||
return new_object
|
||||
|
||||
# the following statements are roughly equivalent
|
||||
x = Foo('bar')
|
||||
x = object_maker(Foo, 'bar')
|
||||
Reference in New Issue
Block a user