Delegation in Python
I would appreciate advice on how to set up delgation in Python. I am continuously implementing a function to test whether a Python Fraction is an integer so I wanted to define a new class, based on Fraction, that includes this new method. But I am not clear on how to delegate from my new class to the existing Fraction class. This is what I have: -- class RF(Fraction): def __new__(self, x, y): super().__new__(self, x, y) def is_integer(self): return self.numerator % self.denominator == 0 def __getattr__(self, attr): return getattr(self, attr) -- which doesn't work. Any advice on how to do this would be much appreciated. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Delegation in Python
On 24/01/2015 23:22, Chris Angelico wrote: > class RF(Fraction): > def is_integer(self): >return self.numerator % self.denominator == 0 Thanks for your help on this. I must admit that nowhere in a lot of searching did I find that delegation is achieved by doing nothing! Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Delegation in Python
On 24/01/2015 23:41, Gary Herron wrote: [snip]> > You can always "monkey-path" the Fraction class on the fly to add a new > method to it. I think most would consider this a bad idea, but it does > work. > Try this: > from fractions import Fraction def is_integer(self): > ... return self.numerator % self.denominator == 0 > ... Fraction.is_integer = is_integer # Monkey-patch Fraction Fraction(1,2).is_integer() > False Fraction(2,1).is_integer() > True Thanks Gary. As Chris says, the method he suggests is problematic since anything delegated returns a Fraction, not an RF. Patching Fraction looks nicer to use even if it is frowned on. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Delegation in Python
On 24/01/2015 23:47, Gary Herron wrote: > On 01/24/2015 03:38 PM, Brian Gladman wrote: >> On 24/01/2015 23:22, Chris Angelico wrote: >>> class RF(Fraction): >>> def is_integer(self): >>> return self.numerator % self.denominator == 0 >> Thanks for your help on this. I must admit that nowhere in a lot of >> searching did I find that delegation is achieved by doing nothing! >> >> Brian > > That's *not* "doing nothing". And it's not even really "delegation". > It's just sub-classing Fraction to add one new method and inherit all > other methods. I realised that - I was being whimsical. I really did want true delgation so that I get an RF returned even when I delegate to Fractions. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Delegation in Python
On 24/01/2015 23:43, Chris Angelico wrote: > On Sun, Jan 25, 2015 at 10:38 AM, Brian Gladman wrote: >> On 24/01/2015 23:22, Chris Angelico wrote: >>> class RF(Fraction): >>> def is_integer(self): >>>return self.numerator % self.denominator == 0 >> >> Thanks for your help on this. I must admit that nowhere in a lot of >> searching did I find that delegation is achieved by doing nothing! > > Hehe :) If you want a technical look at it, what you have is the > fundamental nature of subclassing: you derive from another class, and > your class is identical to that with certain exceptions (in your case, > an additional method). Python's way of handling that is called the > Method Resolution Order or MRO, and you can find info on it on the > web, eg: > > http://python-history.blogspot.com/2010/06/method-resolution-order.html Thanks for the further background. Is there a way of doing delegation rather than sub-classing? That is, can I create a class (say RF) that passes some of its methods to Fraction for implementation but always returns an RF? Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Delegation in Python
On 25/01/2015 01:31, Terry Reedy wrote: > On 1/24/2015 5:57 PM, Brian Gladman wrote: >> I would appreciate advice on how to set up delgation in Python. >> >> I am continuously implementing a function to test whether a Python >> Fraction is an integer > > Since Fractions are reduced to lowest terms, >>>> from fractions import Fraction as F >>>> F(4, 2) > Fraction(2, 1) >>>> F(12, 3) > Fraction(4, 1) > > the test is that the denominator is 1 Thanks Terry, I should have realised this but didn't. >>>> F(12,3).denominator == 1 > True >>>> F(12,5).denominator == 1 > False > > it may not be worth the bother to define a function, > > def fint(F): return F.denominator == 1 > >> so I wanted to define a new class, based on >> Fraction, that includes this new method. > > but if you do, there is little need to make it a method. You are not > overriding an existing method or adding a new special method. The math > module has float and int functions that have *not* been turned into > methods. Ditto for cmath. I would just leave the function a function. Yes, it seems so. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Delegation in Python
On 25/01/2015 00:28, Chris Angelico wrote: > On Sun, Jan 25, 2015 at 11:18 AM, Brian Gladman wrote: >> Is there a way of doing delegation rather than sub-classing? >> >> That is, can I create a class (say RF) that passes some of its methods >> to Fraction for implementation but always returns an RF? > > Hmm. The key here is that you want more than just delegation; you want > to transform every return value. That's not going to be easy. It would > be easiest and cleanest to skip the whole thing, and have a separate > function for what you're doing here - not a method, a stand-alone > function. > > def is_integer(fr): > return fr.numerator % fr.denominator == 0 > > Next best would be the monkey-patching option. Delegation with > transformation is a lot of effort for what you want. Thanks, a part of this was a wish to understand how to map what I can do in other languages into Python. I felt that it might just be possible in Python to avoid having to wrap all the methods of the base class in the derived class. But it seems that __getattr__ etc are not quite as magic as I hoped. Thanks again for your help. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: find all multiplicands and multipliers for a number
On 11/04/2015 03:04, Steven D'Aprano wrote: > It may be a bit slow for very large numbers. On my computer, this takes 20 > seconds: > > py> pyprimes.factors.factorise(2**111+1) > [3, 3, 1777, 3331, 17539, 25781083, 107775231312019L] > > > but that is the nature of factorising large numbers. > > http://code.google.com/p/pyprimes/source/browse/ I don'tknow how well it compares more generally but where large amounts of memory are available a simple sieve works quite well. I have an implementation available here (in Python 3): http://ccgi.gladman.plus.com/wp/?page_id=1500 where: >>> from number_theory import factors >>> print(tuple(factor(2 ** 111 + 1))) ((3, 2), (1777, 1) , (3331, 1), (17539, 1), (25781083, 1), (107775231312019, 1)) runs in less than 2 seconds on my laptop. -- https://mail.python.org/mailman/listinfo/python-list
Re: find all multiplicands and multipliers for a number
On 12/04/2015 15:29, Steven D'Aprano wrote: >> I don'tknow how well it compares more generally but where large amounts >> of memory are available a simple sieve works quite well. I have an >> implementation available here (in Python 3): >> >> http://ccgi.gladman.plus.com/wp/?page_id=1500 > > Um, "simple sieve"? You're using Miller-Rabin to check for candidate prime > factors. I don't think that counts as a simple sieve :-) > What I meant here is that the underlying sieve on which factoring depends - Primes() - is a simple one. I'm sorry that I didn't make this clearer. I agree, of course, that the factoring code itself is more complex than others are experimenting with but I am using it in situations where I want it to work reasonbly well for quite large numbers. > so there is a quite good speedup available from using Miller-Rabin. But it's > not a simple sieve any more. > > By the way, it is possible to get guaranteed deterministic > (non-probabilistic) results with Miller-Rabin, for small integers. By small > I mean less than 2**64. See my pyprimes for details. Yes, I have a more complex version but the simple one works well enough in this context and finds very large primes that would otherwise stall the code. Thanks for taking a look. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: find all multiplicands and multipliers for a number
On 12/04/2015 18:20, Paul Rubin wrote: > Steven D'Aprano writes: >> Um, "simple sieve"? You're using Miller-Rabin to check for candidate >> prime factors. I don't think that counts as a simple sieve :-) > > How does Miller-Rabin help? It has to cost more than trial division. As we factor the number with increasing prime values from a simple sieve, if the number remaining to be factored is still large it can then be efficient to run a prime test to see if what remains is prime. -- https://mail.python.org/mailman/listinfo/python-list
Re: what windows compiler for python 3.5?
On 24/07/2015 12:04, Chris Angelico wrote: > On Fri, Jul 24, 2015 at 8:53 PM, Robin Becker wrote: >> yes I build extensions for reportlab. Unfortunately, despite our MSDN >> subscription to the Visual Studio stuff we have no access to the Visual >> Studio Version 2015. Last one in my downloads is currently 2013. Pity. > > Ah. You may well be somewhat out of luck for the moment, then; I've no > idea what status is during the betas. Once Python 3.5 is released, VS > 2015 should also be available, or else the official compiler for > CPython 3.5 will probably be changed. > > In the meantime, you could possibly ask on python-dev; Steve Dower of > Microsoft hangs out there, and he's the one who's driving the compiler > choice - he may be able to advise as to where to get the prerelease > compiler. Visual Studio 2015 Community was relased earlier this week so there is no need to work with the prerelease version. -- https://mail.python.org/mailman/listinfo/python-list
Re: [RELEASED] Python 3.5.0rc3 is now available
On 08/09/2015 02:35, Larry Hastings wrote: > > > On behalf of the Python development community and the Python 3.5 release > team, I'm relieved to announce the availability of Python 3.5.0rc3, also > known as Python 3.5.0 Release Candidate 3. > > The next release of Python 3.5 will be Python 3.5.0 final. There should > be few (or no) changes to Python 3.5 between rc3 and final. > > This is a preview release, and its use is not recommended for production > settings. > > > You can find Python 3.5.0rc3 here: > > https://www.python.org/downloads/release/python-350rc3/ > > Windows and Mac users: please read the important platform-specific > "Notes on this release" section near the end of that page. > > > Happy hacking, I notice that one new feature that isn't mentioned in the 'what's new' list is the addition of math.gcd() offering a faster and more generic implementation (in that it returns a positive result) of the greatest common divisor operation. Thanks for this and for all your work on Python 3.5. -- https://mail.python.org/mailman/listinfo/python-list
Re: Cryptographically strong random numbers
On 16/10/2015 17:25, Steven D'Aprano wrote: > Hello folks, [snip detail] > randbelow(end): > return a random integer in the half-open interval 0...end > (including 0, excluding end) > > randint(start, end): > return a random integer in the closed interval start...end > (including both start and end) > > randrange([start=0,] end [, step=1]): > return a random integer in the half-open range(start, stop, step) I don't see the third option as being of much, if any, use. Either of the first two would be fine. Of these two, I personally prefer randbelow because it is consistent with what I expect from ranges in Python (randint() always disappoints me because it is inconsistent in this respect). -- https://mail.python.org/mailman/listinfo/python-list