473,671 Members | 2,229 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Refactoring Dilemma

'''
I'm in the middle of a refactoring dilemma.
I have several singletons that I'm turning into modules, for ease of
access.
The usual method is noted as 'Module 1' below.
The new method is noted as 'Module 2'.
Is there any reason NOT to do this that I may be unaware of?
It's easier than remembering to declare global variables at the top of
the function.
'''

# ----------- Module 1.py ------------
# Normal module processing
var = 0

def MyRoutine():
global var
var = 1

MyRoutine()
print var
# ----------- Module 2.py ------------
# 'Self' module processing
import sys
var = 0
self = sys.modules[__name__]

def MyRoutine():
self.var = 1

MyRoutine()
print var

Sep 10 '06 #1
7 1114
Kamilche wrote:
'''
I'm in the middle of a refactoring dilemma.
I have several singletons that I'm turning into modules, for ease of
access.
The usual method is noted as 'Module 1' below.
The new method is noted as 'Module 2'.
Is there any reason NOT to do this that I may be unaware of?
It's easier than remembering to declare global variables at the top of
the function.
'''

# ----------- Module 1.py ------------
# Normal module processing
var = 0

def MyRoutine():
global var
var = 1

MyRoutine()
print var
# ----------- Module 2.py ------------
# 'Self' module processing
import sys
var = 0
self = sys.modules[__name__]

def MyRoutine():
self.var = 1

MyRoutine()
print var

What's wrong with
<code>
def MyRoutine():
return 1

var = MyRoutine()
</code>
?

George

Sep 10 '06 #2
Kamilche wrote:
'''
I'm in the middle of a refactoring dilemma.
I have several singletons that I'm turning into modules, for ease of
access.
The usual method is noted as 'Module 1' below.
The new method is noted as 'Module 2'.
Is there any reason NOT to do this that I may be unaware of?
It's easier than remembering to declare global variables at the top of
the function.
'''

# ----------- Module 1.py ------------
# Normal module processing
var = 0

def MyRoutine():
global var
var = 1

MyRoutine()
print var
# ----------- Module 2.py ------------
# 'Self' module processing
import sys
var = 0
self = sys.modules[__name__]

def MyRoutine():
self.var = 1

MyRoutine()
print var
I don't see any major problem with it. In fact, I think it's a very
good idea to do this, rather than use global statements, when using
module as a singleton class.

I recently made the same transition myself, though I solved it a bit
differently. I used a decorator to pass the module as the first
argument (actually it passes a proxy to module's global dict, since the
module itself isn't accesible from the function object).

def modmethod(func) :
class modproxy(object ):
__getattribute_ _ = func.func_globa ls.__getitem__
__setattr__ = func.func_globa ls.__setitem__
self = modproxy()
def call_with_modul e(*args,**kwarg s):
return func(self,*args ,**kwargs)
call_with_modul e.func_name = func.func_name
return call_with_modul e

@modmethod
def MyRoutine(self) :
self.var = 1

MyRoutine()
print var

One problem with my decorator is it makes stack traces a little
bloated. (Also attribute errors are raised as KeyError, but that's
easily fixable.) Other than that, I've been running it for awhile
without any problems. I doubt your approach would have many problems,
either.
Carl Banks

Sep 10 '06 #3
George Sakkis wrote:
Kamilche wrote:
'''
I'm in the middle of a refactoring dilemma.
I have several singletons that I'm turning into modules, for ease of
access.
The usual method is noted as 'Module 1' below.
The new method is noted as 'Module 2'.
Is there any reason NOT to do this that I may be unaware of?
It's easier than remembering to declare global variables at the top of
the function.
'''

# ----------- Module 1.py ------------
# Normal module processing
var = 0

def MyRoutine():
global var
var = 1

MyRoutine()
print var
# ----------- Module 2.py ------------
# 'Self' module processing
import sys
var = 0
self = sys.modules[__name__]

def MyRoutine():
self.var = 1

MyRoutine()
print var


What's wrong with
<code>
def MyRoutine():
return 1

var = MyRoutine()
</code>
?

Kamilche simplified things in his example that obscured the main use
case. Short story is, var is considered a state of the module, and
MyRoutine() is designed to be called from outside the module to modify
the state. Your suggestion can only modify the state of the module
from within, so it won't do.

More detailed discussion:

A common piece of advice when people ask "how can I implement a
singleton in Python" is to use a module. A module, after all, is a
singleton object.

But there's a big problem using a module as a singleton: you need to
use then global statement to rebind module-level variables. Which
means that if you want your module to have lots of modifyable state,
most likely you'll have to use a bunch global statements. And that's a
major pain in the neck when you have to do it a lot and in many
functions.

In these cases, it would be nice if a module could access its own state
in the same way that an instance does, that is, as an attribute. My
approach of using a decorator to pass in a module proxy, and Kamilche's
approach of binding the module object to self, both accomplish this.
Internally, the module behaves very much like a class instance.
Functions in the module act almost exactly like bound methods, and
module-level variables act like instance attributes. The difference
between writing a module and a singleton class thus becomes mostly a
matter of indentation.

In fact, when I made a major switch from using singleton classes to
modules, I was able to change it by dedenting once, and pasting a
@modmethod decoration above each method, with very few other changes.

Carl Banks

Carl Banks

Sep 10 '06 #4
Carl Banks wrote:
Kamilche wrote:
'''
I'm in the middle of a refactoring dilemma.
I have several singletons that I'm turning into modules, for ease of
access.
The usual method is noted as 'Module 1' below.
The new method is noted as 'Module 2'.
Is there any reason NOT to do this that I may be unaware of?
It's easier than remembering to declare global variables at the top of
the function.
'''

# ----------- Module 1.py ------------
# Normal module processing
var = 0

def MyRoutine():
global var
var = 1

MyRoutine()
print var
# ----------- Module 2.py ------------
# 'Self' module processing
import sys
var = 0
self = sys.modules[__name__]

def MyRoutine():
self.var = 1

MyRoutine()
print var

I don't see any major problem with it. In fact, I think it's a very
good idea to do this, rather than use global statements, when using
module as a singleton class.

I recently made the same transition myself, though I solved it a bit
differently. I used a decorator to pass the module as the first
argument (actually it passes a proxy to module's global dict, since the
module itself isn't accesible from the function object).

def modmethod(func) :
class modproxy(object ):
__getattribute_ _ = func.func_globa ls.__getitem__
__setattr__ = func.func_globa ls.__setitem__
self = modproxy()
def call_with_modul e(*args,**kwarg s):
return func(self,*args ,**kwargs)
call_with_modul e.func_name = func.func_name
return call_with_modul e

@modmethod
def MyRoutine(self) :
self.var = 1

MyRoutine()
print var
This looks quite hackish, both the implementation and the usage; most
people would get confused when they didn't find var's assignment at
global scope. I prefer the the simple global statements if they aren't
that many, otherwise the assignment of the module to self is also fine.

George

Sep 11 '06 #5

George Sakkis wrote:
Carl Banks wrote:
I don't see any major problem with it. In fact, I think it's a very
good idea to do this, rather than use global statements, when using
module as a singleton class.

I recently made the same transition myself, though I solved it a bit
differently. I used a decorator to pass the module as the first
argument (actually it passes a proxy to module's global dict, since the
module itself isn't accesible from the function object).

def modmethod(func) :
class modproxy(object ):
__getattribute_ _ = func.func_globa ls.__getitem__
__setattr__ = func.func_globa ls.__setitem__
self = modproxy()
def call_with_modul e(*args,**kwarg s):
return func(self,*args ,**kwargs)
call_with_modul e.func_name = func.func_name
return call_with_modul e

@modmethod
def MyRoutine(self) :
self.var = 1

MyRoutine()
print var

This looks quite hackish, both the implementation and the usage;
Once again, the function MyRoutine is intended to be called from
another module. The usage I have here is just an example demonstrating
that var is in the module's dict. Please keep this in mind when
criticizing usage. The intended usage would be something like this
(from another module):

from xxx import yyy
yyy.MyRoutine()

As far as the caller is concerned, yyy could be a module using globals,
a module with this "hack", or a class instance, or something else. It
doesn't matter; usage is the same in all three cases.

As for the implementation. ..
most
people would get confused when they didn't find var's assignment at
global scope. I prefer the the simple global statements if they aren't
that many, otherwise the assignment of the module to self is also fine.
For ordinary modules that might have one or two serial number counters
or debug flags or whatnot, I agree. For modules that have lots of
state and act more like class instances than modules, the massive
amounts of globals are ugly and error prone. In that case you should
either use a regular class, or tolerate the "hack"; don't use a bunch
of globals.

I think a simple comment at the top could take care of any confusion
about what's happening. Since it mimics how a class works, it won't be
anything completely new.

YMMV.

Carl Banks

Sep 11 '06 #6
George Sakkis wrote:
I prefer the the simple global statements if they aren't
that many, otherwise the assignment of the module to self is also fine.
I replied to this article, and then canceled the reply (but that never
works), thinking you were criticizing the general concept of "module as
a singleton" and not just my approach. I should learn to read. I
apologize for the misunderstandin g.

I do agree my implementation is a little hacky, although IMHO it feels
to fit in with the way classes work better, which appeals to me but
probably not most people :). For one thing, the methods have the
explicit self argument, like regular classes. For another, it uses a
decorator to affect the binding of the modules. In regular classes,
functions are instance methods by default, and become class methods or
static methods with a decorator. I like to think of modules as having
a special metaclass that treats functions as static methods by default,
and uses a decorator to get an instance method. (Even though that
isn't remotely how it works, it fits how it would work if you were
implementing modules based on classes.)

Having said that, I've no problem with Kamilche's approach. The real
evil in my mind is using lots of global statements, and anything you
can do to stay away from that is a good thing.
Carl Banks

Sep 11 '06 #7
Kamilche wrote:
Is there any reason NOT to do this that I may be unaware of?
[snip]
# ----------- Module 2.py ------------
# 'Self' module processing
import sys
var = 0
self = sys.modules[__name__]

def MyRoutine():
self.var = 1

MyRoutine()
print var
Looks basically fine to me, but I'd probably write it as::

_self = __import__(__na me__)

Then you don't need to import sys. I'd also use a leading underscore
for "self" so that it's clearly marked as a module-internal attribute.

STeVe
Sep 11 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
2024
by: Peter Dembinski | last post by:
I am trying to write Master Thesis on refactoring Python code. Where should I look for information? -- http://www.dembiñski.prv.pl
4
1599
by: | last post by:
Hi, Refactoring a winform causes problems if moving this form to a subdirectory in the same project. What is the workaround for this and will this be fixed in future? Thanks /BOB
0
1969
by: Andre Baresel | last post by:
Hello together, just a year ago I was searching arround for a tool supporting refactoring for c++. I've seen implementations for java and was impressed how an IDE can help with such a feature. Just rename classes / member / parameter with a mouse click. reduce the size of a method by transforming parts of it into a seperate
2
2100
by: Sachin Garg | last post by:
Hi, I was trying to find (like many others here) a tool for refactoring C++ code as I have lately been noticing that I spend most of my coding time doing refactoring and some refactoring which I skip, due to the enormous effort it seems to require, usually comes back to me with larger costs. I read a few comp.lang.c++ threads over past few years regarding
6
3348
by: Dean Ware | last post by:
Hi, I am part way through developing a C++ application. I am developing it on my own and using VC++ 6.0. I am now at the stage where I wish to start tidying up my code. I have lots of superfluous code that is hard to be sure about removing. For example, I have classes that are ONLY used in methods that are never
8
2008
by: Frank Rizzo | last post by:
I keep hearing this term thrown around. What does it mean in the context of code? Can someone provide a definition and example using concrete code? Thanks.
15
4389
by: Simon Cooke | last post by:
Does anyone know of any tools for refactoring header files? We're using a third party codebase at work, and pretty much every file includes a 50Mb precompiled header file. I'm looking for a tool that will let us figure out which header files are actually needed by each .cpp, and allow us to break this up so that we're not including the world in each one. Ideally, the same tool would also recognize where #includes can be replaced with...
16
3156
by: hzmonte | last post by:
Correct me if I am wrong, declaring formal parameters of functions as const, if they should not be/is not changed, has 2 benefits; 1. It tells the program that calls this function that the parameter will not be changed - so don't worry. 2. It tells the implementor and the maintainer of this function that the parameter should not be changed inside the function. And it is for this reason that some people advocate that it is a good idea to...
2
1812
by: HendrikLeder | last post by:
Hello everybody :-) Next year I`ll write my diploma in computer science for business (It`s a degree in Germany) and I`ve some questions about the topic. The diploma will handle about refactoring of xml-schemes and a transformation of all instances (the xml-documents) with XSLT-scripts. The idea of the diploma is, that in nearly every company xml schemes are used. And (like Heraklit said "Panta rhei" - everthing is flowing) the business...
0
8476
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8393
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8914
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8598
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8670
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7433
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6223
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4224
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
1809
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.