Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    80
    Rep Power
    2

    Property-Encapsulated Objects?


    I'm fairly sure this isn't "Pythonic", per se, but forgive me.

    I've reduced this code here from my main module into it's base components for the test:

    Code:
    class sketch():
    	def __setattr__(self,att,value):
    		self.__dict__[att]=value
    	def __repr__(self):
    		return 'sketch('+str(self.__dict__)[1:][:-1]+')'
    	def __init__(self,**sketchargs):
    		self.__dict__=sketchargs
    And here's the excerpt from my pygame stuff (with the actual pygame stuff removed):

    Code:
    game=sketch()
    game.clock=pygame.time.Clock()
    game.ssize=(960,720)
    game.trim=40
    game.killswitch=False
    game.fontsize=12
    game.insize=lambda:(game.ssize[0]-game.trim,game.ssize[1]-game.trim)
    game.inpos=lambda:(int(game.trim/2),int(game.trim/2))
    See, I want to make the screen size adjustable. However, whenever I use insize, this creates this kind of thing with the code:

    Code:
    game.layers.append((newbox(game.insize(),col.dimgray,col.black,200),game.inpos()))
    Basically, every time I call it up, I have to put the () at the end to not return a lambda.

    Is there any way to encapsulate a function so that it behaves like a property without defining it as a property of the base class? Because "sketch" is supposed to be an abstract class, and I want it to have some calculated values that are bound to lambda calls, without those parentheses to foul me up.
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,955
    Rep Power
    481
    I do not comprehend your question.
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    194
    Rep Power
    3
    Is there any way to encapsulate a function so that it behaves like a property without defining it as a property of the base class?
    If you want a class method that behaves like an attribute then you can use the @property decorator.

    Ex:
    python Code:
    class MyClass(object):
        def __init__(self,data):
            self.data = data
     
        @property
        def fake_attrib(self):
            return self.data**2
    Code:
    >>> a = MyClass(5)
    >>> a.fake_attrib
    25
    See, I want to make the screen size adjustable.
    If all you want is to have an adjustable screen size in a pygame then that is fairly simple. Just blit everything to a surface of the original size and then scale it to the new size of the screen before blitting to the actual screen. You will need to catch VIDEORESIZE events in your event loop and reset the mode of the display accordingly.
    python Code:
    import sys,os
    import pygame as pg
     
    START_SIZE = (500,500)
     
    class Control(object):
        def __init__(self):
            os.environ["SDL_VIDEO_CENTERED"] = '1'
            pg.init()
            self.screen = pg.display.set_mode(START_SIZE,pg.RESIZABLE)
            self.current_resolution = START_SIZE
            self.clock = pg.time.Clock()
            self.fps = 60.0
            self.done = False
     
        def event_loop(self):
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    self.done = True
                elif event.type == pg.VIDEORESIZE:
                    self.current_resolution = event.size
                    self.screen = pg.display.set_mode(event.size,pg.RESIZABLE)
     
        def update(self):
            image = pg.Surface(START_SIZE).convert()
            pg.draw.polygon(image,(255,0,0),[(0,500),(500,500),(250,0)])
            if self.current_resolution != START_SIZE:
                image = pg.transform.smoothscale(image, self.current_resolution)
            self.screen.blit(image,(0,0))
     
        def main(self):
            while not self.done:
                self.event_loop()
                self.update()
                pg.display.update()
                self.clock.tick(self.fps)
     
     
    if __name__ == "__main__":
        run_it = Control()
        run_it.main()
        pg.quit();sys.exit()
    If you want to maintain aspect ratio then you will have to do some extra stuff; but it shouldn't really be anything complicated.

    -Mek

    Comments on this post

    • zxq9 agrees : Rare example of providing a correct answer to a partial X Y problem.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    80
    Rep Power
    2
    @Mekire:

    Yeah, I want to do properties, but I want to be able to just assign them direct, as if I were assigning it to a variable instead of a method.

    Like:

    Code:
    >>> global start,end
    >>> start=3
    >>> end=lambda:start+2
    >>> end()
    5
    >>> start=4
    >>> end()
    6
    >>> end
    <function <lambda> at 0x01307F70>
    I want "end" to be something other than a lambda, that essentially just returns the value of itself (given by "end()") whenever it's referenced (with "end"). In essence, a lambda within an object that causes that lambda to behave like a property.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    194
    Rep Power
    3
    How is that different from what I just showed you?

    python Code:
    class MyClass(object):
        def __init__(self,start):
            self.start = start
     
        @property
        def end(self):
            return self.start+2
    Code:
    >>> a = MyClass(3)
    >>> a.start
    3
    >>> a.end
    5
    >>> a.start = 4
    >>> a.end
    6
    >>>
    I would also like to say that you are using classes in a very odd (wrong) way. By overloading setattr in the way you have, you have made it so you can add absolutely anything to your class as an attribute.

    -Mek

    Comments on this post

    • b49P23TIvg agrees : Yes, I've never before seen entirely replacing Object.__dict__
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Location
    Usually Japan when not on contract
    Posts
    240
    Rep Power
    12
    Originally Posted by Mr909
    ...I want "end" to be something other than a lambda...
    It seems more that you want Python to be something other than Python. If I had my way Python would be more FP oriented. Its not. But Guido chose the idioms he has chosen for a reason, and he's written about them at length. The result is a profoundly self-coherent language. He went to lengths to keep Java-style b&d "self protections" out of the language so it is infinitely hackable. In other words, Python philosophy is that we're all consenting adults so nothing is really off-limits or private (you can even redefine the dot operator if you're so inclined...).

    Most of the time doing stuff like that is a clear indicator of a design problem. Some of the time it is an indicator that Python isn't the tool for the job (and in these rare cases there is Common Lisp/CLOS or Erlang, or Clojure, or whatever). About once a year some hacked up black magic makes everything better. Your case doesn't fall into this category, though.

    Proverb of the day: "No matter how far you've gone down the road, turn back."
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    114
    Rep Power
    3
    Code:
    import types
    
    
    class sketch:
    
        ...
    
        def __getattribute__(self, name):
            attr = object.__getattribute__(self, name)
            if isinstance(attr, types.LambdaType):
                return attr()
            return attr
    Also I'm not sure why you're overriding __setattr__ to do the same thing that it does by default?
    Last edited by Nyktos; July 25th, 2013 at 07:43 AM.
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    80
    Rep Power
    2
    Originally Posted by Nyktos
    Code:
    import types
    
    
    class sketch:
    
        ...
    
        def __getattribute__(self, name):
            attr = object.__getattribute__(self, name)
            if isinstance(attr, types.LambdaType):
                return attr()
            return attr
    Also I'm not sure why you're overriding __setattr__ to do the same thing that it does by default?
    It never calls an attribute error for attributes that aren't set by default. It's a go-around for that, an abstract base class if you will.

    Code:
    >>> test=object()
    >>> test.a=20
    
    Traceback (most recent call last):
      File "<pyshell#1>", line 1, in <module>
        test.a=20
    AttributeError: 'object' object has no attribute 'a'
    >>> from pygos.sketchbook import sketch
    >>> test=sketch()
    >>> test.a=20
    >>> test.a
    20
    Originally Posted by zxq9
    It seems more that you want Python to be something other than Python. If I had my way Python would be more FP oriented. Its not. But Guido chose the idioms he has chosen for a reason, and he's written about them at length. The result is a profoundly self-coherent language. He went to lengths to keep Java-style b&d "self protections" out of the language so it is infinitely hackable. In other words, Python philosophy is that we're all consenting adults so nothing is really off-limits or private (you can even redefine the dot operator if you're so inclined...).

    Most of the time doing stuff like that is a clear indicator of a design problem. Some of the time it is an indicator that Python isn't the tool for the job (and in these rare cases there is Common Lisp/CLOS or Erlang, or Clojure, or whatever). About once a year some hacked up black magic makes everything better. Your case doesn't fall into this category, though.

    Proverb of the day: "No matter how far you've gone down the road, turn back."
    I found Python. I saw Python. I liked Python.
    And you're right, I don't use normal idioms. This junk works for me. I use consume(), and sketch(), and I use .__dict__. But for me, this is smooth, this is easy, and I've yet to encounter a whole lot of problems because of it. I mean, here, game.insize() still returns exactly the value I need, I just thought maybe I can find a way to make it look a bit neater, because it looks like a method call when it isn't.

    If I've yet to take a noticeable speed hit or encounter a significant number of errors (that I wouldn't encounter with another method), it isn't a "design problem" in my eyes.

    Originally Posted by Mekire
    How is that different from what I just showed you?
    Exactly that, without the "a." at the beginning, not attached to a class, just free-floating. I want an object that is "end" while behaving like a property.

    Originally Posted by Mekire
    How is that different from what I just showed you?

    I would also like to say that you are using classes in a very odd (wrong) way. By overloading setattr in the way you have, you have made it so you can add absolutely anything to your class as an attribute.

    -Mek
    The main usage for this system (the code for which was not included here) is so that I can have my module refer to it's pieces without dependency on them. It has another method that allows for fast reformatting on the go, and it's attached to another system for quick references to parts of a larger whole. I knew I took the lock off. I did that for a reason. I wanted to play with it.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    114
    Rep Power
    3
    Originally Posted by Mr909
    It never calls an attribute error for attributes that aren't set by default. It's a go-around for that, an abstract base class if you will.
    ...What? The default __setattr__ does not raise attribute errors for attributes that don't exist.

    Originally Posted by Mr909
    Exactly that, without the "a." at the beginning, not attached to a class, just free-floating. I want an object that is "end" while behaving like a property.
    Okay, well in that case: there's no way to do that. Sorry. The way I showed allows you to do it with instance attributes, but there's no way for a global/local variable to exhibit behaviour like that.

    Well, actually, you might be able to use an import hook and subclass ModuleType(!!!) to make module attributes that behave that way. I really don't feel like figuring out the logistics of something like that, and I'm not sure it would work properly with references to the name from within the module.
    Last edited by Nyktos; July 25th, 2013 at 05:45 PM.
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    194
    Rep Power
    3
    Originally Posted by Mr909
    It never calls an attribute error for attributes that aren't set by default. It's a go-around for that, an abstract base class if you will.
    I was mistakenly thinking that you would be getting AttributeErrors too; but Nyktos is correct. You overloaded __setattr__ with exactly what it does by default.

    -Mek
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    80
    Rep Power
    2
    Originally Posted by Nyktos
    ...What? The default __setattr__ does not raise attribute errors for attributes that don't exist.
    With all due respect and no sarcasm intended, sir, I'm pretty sure I already posted an instance of something doing exactly that.

    Code:
    >>> test=object()
    >>> test.a=20
    Traceback (most recent call last):
      File "<pyshell#1>", line 1, in <module>
        test.a=20
    AttributeError: 'object' object has no attribute 'a'
    >>> from pygos.sketchbook import sketch
    >>> test=sketch()
    >>> test.a=20
    >>> test.a
    20
    Originally Posted by Nyktos
    Okay, well in that case: there's no way to do that. Sorry. The way I showed allows you to do it with instance attributes, but there's no way for a global/local variable to exhibit behaviour like that.

    Well, actually, you might be able to use an import hook and subclass ModuleType(!!!) to make module attributes that behave that way. I really don't feel like figuring out the logistics of something like that, and I'm not sure it would work properly with references to the name from within the module.
    Thanks for trying, I imagined it might be the case. The hassle of putting () at the end of everything probably doesn't merit a large scale solution anyway.

    And once more, I'm sorry I don't agree with you guys on the meaning of "Pythonic" code. I can't show you why I feel my way is justified, but I think it is an interesting and effective way to get what I want done. I sincerely apologize and thank you very much for helping me anyway. You guys really are great mentors who I look up to; It's just not in my nature to agree with a standard for sake of agreement.
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    194
    Rep Power
    3
    That is actually interesting.

    If you make a completely empty class:
    Code:
    class C(object):
        pass
    and you try to inject an attribute, it works just fine.
    Code:
    >>> a = C()
    >>> a.x = 5
    >>> a.x
    5
    but if you directly make an instance of object it fails:
    Code:
    >>> b = object()
    >>> b.x = 5
    Traceback (most recent call last):
      File "<interactive input>", line 1, in <module>
    AttributeError: 'object' object has no attribute 'x'
    >>>
    Interesting,
    -Mek
    Last edited by Mekire; July 25th, 2013 at 10:25 PM.
  24. #13
  25. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    114
    Rep Power
    3
    This is because object doesn't have a __dict__. You can make a class without one using __slots__:
    Code:
    >>> class Spam:
    ...     __slots__ = []
    ...
    >>> s = Spam()
    >>> s.x = 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Spam' object has no attribute 'x'
    User-defined classes that don't use __slots__ always have a __dict__, and your __setattr__ implementation still wouldn't work on the ones that don't.

    Comments on this post

    • Mekire agrees : I was unaware of slots; more research is in order for me (don't worry I don't intend to actually use it).
  26. #14
  27. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Location
    Usually Japan when not on contract
    Posts
    240
    Rep Power
    12
    Originally Posted by Mr909
    And once more, I'm sorry I don't agree with you guys on the meaning of "Pythonic" code. I can't show you why I feel my way is justified, but I think it is an interesting and effective way to get what I want done. I sincerely apologize and thank you very much for helping me anyway. You guys really are great mentors who I look up to; It's just not in my nature to agree with a standard for sake of agreement.
    Bit of a philosophic post follows, but hopefully you find it in good nature (you're smart, I sincerely believe it worthwhile to spend time expressing this) and at least worthy of some contemplation, despite my inadequate conveyance of the ideas.

    You never have to apologize for not agreeing with an idea. But as far as the meaning of "Pythonic", its not really open for much debate, as the language creator, Guido van Rossum, has defined this at length. You understand enough about the mechanics of a system to see how you can make it do what you want. More importantly, you have learned how to learn enough about a system to make it do what you want (Golden Goose get!). The next thing to come to grips with is how programs are not just a collection of constructs the programmer can command, but that programs are semantic prescriptions of process.

    As a community, industry and academic field we're only beginning to really understand the implications of this today. Gerry Sussman once said that the Egyptians mistakenly thought that the important thing about geometry was the practice of using surveying tools in the same way we mistakenly think that Computer Science has something fundamental to do with the use of computers. The Greeks eventually realized that geometry was not about using surveying tools to measure stuff at all, rather it was about developing a formal system of deduction, proof and expressive notations for abstract, but self-consistent ideas. In a similar way we are beginning to realize that programming is not really about telling a computer to do this or that, but rather how to formalize and refine our intuitions about process.

    The messiness of the solutions you are seeking are a sign that you're fighting the language and not working within it. What you're doing is applying your new, non Python, semantics to the CPython runtime on your computer. This interferes greatly not just with the concept of writing Python in Python (you've probably heard the old joke that "a Real Programmer can write FORTRAN in any language"), but in very practical terms it will wind up botching your system once it reaches a certain size.

    Its very similar to the (oft lampooned and criticized) way that Stephen Bourne used macros to make the C source for the original Bourne Shell look superficially like ALGOL, just because he was an ALGOL fan and (most critically) he never thought anyone would read the code! Maintenance of the original Bourne Shell code was a nightmare because of this refusal to just write C as C (here is a [link to the macro file]... its hilarious if you know anything about C and ALGOL). Nothing did what anyone expected in the code, because it was no longer expressed as C (whether built on a C compiler or not), nor actually ALGOL. It was a failed experiment. It is interesting to see that the product of the work based on this weird, incoherent notation is itself a language loaded with weird, incoherent idiosyncrasies. sh/Bash itself can be held up as an example of how messy a language can get when a clear philosophy is not expressed as a concrete set of syntactic rules. Idiosyncrasy can banish a programmer's sanity in a hurry -- introducing it is a bad thing.

    Some points of Guido's philosophy stand in stark contrast to that of Larry Wall's (original) vision for Perl. Perl's motto is "there is more than one way to do it" and it permits just as much backhacking as Python does. Guido's motto is "there should be one, and preferably only one, correct way to do it." This is a bit tongue-in-cheek, of course, but the core concept stands as the foundation of designing the language around idioms that have evolved and been declared "Pythonic". The difference this has produced in the languages and the runtimes themselves is profound. The source for the Perl runtime is a special-case minefield that has been given enough attention to make it work -- but there's a lot of hackish stuff going on in there. The CPython runtime is a relatively sane, self-consistent system. It lacks a lot of speed hacks that the Perl runtime is famous for -- but the basic defense for this is that if you really need performance then you should either write the performance-needy code in C (and a lot of effort has been expended making this natural and easy in Python) or you shouldn't be using a scripting language to begin with.

    I can appreciate what you are trying to do, but its in such deep conflict with the philosophy of Python itself that you're better off with a different language if this is what you want to do. I wasn't joking about Common Lisp and CLOS in my previous post. Perl might also suit you better, as unexpected behavior and backhacks are the norm there (Perl code often looks like comic characters swearing anyway, so no harm done).

    There are plenty of things I don't like about the way Python works. But it is always the case that trying to make Python change to suit me is a lot worse idea than just making my code fit the Pythonic way of doing things. In the places where Python really doesn't do things the way I want I just use another language.

    Comments on this post

    • Mekire agrees : The ALGOL hack was pretty amusing. I also found this while exploring. http://stackoverflow.com/questions/652788/what-is-the-worst-real-world-macros-pre-processor-abuse-youve-ever-come-across
  28. #15
  29. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,955
    Rep Power
    481

    still baffled, please don't explain.


    Unimportant, but I still don't understand this thread. Is Mr909's only concern that he wants fewer parentheses? If so, lisp is poorly advised))))). To me, and I could be the dolt, incomprehensible doesn't equate with smart. I recommend for Mr909 to implement his python systems as pure cross talk between generators.


    Other thoughts along the way:
    • Fewer parentheses while avoiding the means python provides to make it possible. Mr909 doesn't permit properties, which generalizes to "no callables that wrap callables". Based solely on my current knowledge of python, this is insane.
    • Mr909 also seems to want a magical entity that returns needed values without explicitly asking. Or implicitly asking. Such programs exist, except that they usually have unwanted consequences. These programs are called "viruses".
    [code]Code tags[/code] are essential for python code and Makefiles!
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo