Python Forum
Is there another way to do a bunch of methods calls ?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Is there another way to do a bunch of methods calls ?
#1
class Test:
	def __init__(self):
		self.a = 1
		
	def one(self):
		self.a += 1
		return self
		
	def two(self):
		self.a += 2
		return self
		
	def three(self):
		self.a += 3
		return self

test = Test() \
	.one() \
	.two() \
	.three()
	
print(test.a)
99 percent of computer problems exists between chair and keyboard.
Reply
#2
test.one()
test.two()
test.three()

#  or ...

for f in [test.one, test.two, test.three]:
   f()
What exactly are you looking for?
Reply
#3
I'm looking for another style with less typing.
This looks nicer. Just wondering if python has another way ?
test = (Test()
   .one()
   .two()
   .three())
99 percent of computer problems exists between chair and keyboard.
Reply
#4
this is ugly and non-pythonic
please, don't do it
Reply
#5
I'm looking for ways to set items up in my classes.
Right now looking at dict for args and kwargs.
import pygame
from pyscene.objects import PySceneObject
from pyscene.tool import gradient, twist

# Text are static. Can be transform in Text Click.
# Text can have a hilight color.
# Text can have colorful text

class TextInfo:
    def __init__(self, color, alpha):
        self.alpha = alpha
        self.image = None
        self.r_image = None
        self.color = twist.colorx(color)

    def set_color(self, color):
        self.color = twist.colorx(color)

# color takes pygame.Color args or pygame.Surface
class Text(PySceneObject):
    keys = ['text',
            'pos',
            'font',
            'color',
            'alha',
            'group',
            'callback',
            'allow_bindings',
            'hilight',
            'toggle',
            'blink',
            'angle']

    default = { 'text':'Text',
                'pos':(0,0),
                'font':None,
                'color':'white',
                'alha':None,
                'group':None,
                'callback':None,    # (callback, pydata=None)
                'allow_bindings':True,
                'hilight':None,     # (color, alpha=None)
                'toggle':None,      # (color, alpha=None)
                'blink':None,       # (color, time_interval, interval, alpha=None)
                'angle':None
                }

    def __init__(self, parent, text, x, y, font=None, color='white', group=None,
        callback=None, pydata=None, alpha=None, allow_bindings=True):

        PySceneObject.__init__(self, parent, (x, y), 'Text', group, allow_bindings)
        if font is None:
            self._font = pygame.font.Font(None, 24)
        else:
            self._font = font

        self._info = {'base': TextInfo(color, alpha)}
        self._text = text
        self._angle = None
        self._r_rect = None
        self._render(self._info['base'])
        self.callback = callback
        self.pydata = pydata

        if allow_bindings:
            parent.bind_blit(self._key + 'blit__', self.blit)

    def set_callback(self, callback, pydata=None):
        self.callback = callback
        self.pydata = pydata
        return self

    def event_mousemotion(self, event, key, pydata):
        if event is None:
            self._hover = False
            if self._info.get('blink', False):
                if self._parent.timer[self._key + 'timer__'].stop:
                    self._parent.timer.start(self._key + 'timer__')
        elif self.enable:
            self._hover = self._rect.collidepoint(event.pos)
            if self._info.get('hover', False) and self._hover:
                if self._info.get('blink', False):
                    self._parent.timer.stop(self._key + 'timer__')
            else:
                if self._info.get('blink', False):
                    if self._parent.timer[self._key + 'timer__'].stop:
                        self._parent.timer.start(self._key + 'timer__')

    def event_mousebuttondown(self, event, key, pydata):
        PySceneObject.event_mousebuttondown(self, event, key, pydata)

        if event.button == 1:
            if self.callback and self._hover:
                self.callback(self, self.pydata)

    def set_hilight(self, color, alpha=None):
        if self._info.get('hover', False):
            self._info['hover'].set_color(color)
            self._info['hover'].alpha = alpha
        else:
            self._info['hover'] = TextInfo(color, alpha)
        self._render(self._info['hover'])
        return self

    def set_toggle(self, color, alpha=None):
        if self._group is None:
            self.allow_toggle = True

        if self._info.get('toggle', False):
            self._info['toggle'].set_color(color)
            self._info['toggle'].alpha = alpha
        else:
            self._info['toggle'] = TextInfo(color, alpha)
        self._render(self._info['toggle'])
        return self

    def set_blink(self, color, time_interval, interval, alpha=None):
        if self._info.get('blink', False):
            self._info['blink'].set_color(color)
            self._info['blink'].alpha = alpha
        else:
            self._info['blink'] = TextInfo(color, alpha)

        self._info['blink'].interval = interval
        self._info['blink'].time_interval = time_interval
        self._info['blink'].blink = False
        self._parent.timer.add(self._key + 'timer__', interval, self._timer_blink, 'time')
        self._render(self._info['blink'])
        return self

    def _timer_blink(self, info):
        if info.pydata == 'time':
            self._info['blink'].blink = False
            info.pydata = 'blink'
            info.interval = self._info['blink'].time_interval
        else:
            self._info['blink'].blink = True
            info.pydata = 'time'
            info.interval = self._info['blink'].interval

    def _render(self, info):
        if isinstance(info.color, pygame.Surface):
            surface = self._font.render(self._text, 1, (255,255,255))
        else:
            surface = self._font.render(self._text, 1, info.color)
        self._rect = surface.get_rect()
        self._anchor_position()

        if isinstance(info.color, pygame.Surface):
            info.image = gradient.apply_surface(surface, info.color)
            if self._angle is not None:
                info.r_image = pygame.transform.rotate(info.image, self._angle)
                self._r_rect = info.r_image.get_rect()
                self._r_rect.center = self._rect.center
        else:
            info.image = surface
            if info.alpha:
                twist.ghost(info.image, info.alpha)

            if self._angle is not None:
                info.r_image = pygame.transform.rotate(info.image, self._angle)
                self._r_rect = info.r_image.get_rect()
                self._r_rect.center = self._rect.center

    def blit(self, surface, position=None):
        rect = [self._r_rect, self._rect][self._angle is None]
        rect = self._draw_rect(rect, position)
        attr = ['r_image', 'image'][self._angle is None]

        if self._info.get('toggle', False) and self._toggle:
            surface.blit(getattr(self._info['toggle'], attr), rect)
        elif self._info.get('hover', False) and self._hover:
            surface.blit(getattr(self._info['hover'], attr), rect)
        elif self._info.get('blink', False) and self._info['blink'].blink:
            surface.blit(getattr(self._info['blink'], attr), rect)
        else:
            surface.blit(getattr(self._info['base'], attr), rect)

    def _do_render(self):
        for key in self._info.keys():
            self._render(self._info[key])

    def set_font(self, font):
        self._font = font
        self._do_render()
        return self

    def set_text(self, text):
        self._text = text
        self._do_render()
        return self

    def set_color(self, color, alpha=None):
        self._info['base'].set_color(color)
        self._info['base'].alpha = alpha
        self._render(self._info['base'])
        return self

    def set_position(self, x, y=None):
        PySceneObject.set_position(self, x, y)
        if self._r_rect:
            self._anchor_position(self_r_rect)
        return self

    def set_angle(self, angle):
        self._angle = angle
        self._do_render()
        return self

    def __repr__(self):
        return "Text({0})".format(self._text)
99 percent of computer problems exists between chair and keyboard.
Reply
#6
(Jan-02-2018, 02:55 PM)Windspar Wrote: I'm looking for another style with less typing.
This looks nicer. Just wondering if python has another way ?
test = (Test()
   .one()
   .two()
   .three())

I agree with buran about this type of code. I think a combination of good default values and maybe a "configuration" dict or namedtuple would be the better way to approach this. This weekend, I was playing around with implementing some of the mechanics of Arkham Horror (https://www.fantasyflightgames.com/en/pr...am-horror/) and was doing something very similar to read player/monster data from a JSON file and quickly instantiate objects.
Reply
#7
I believe this is known as the builder pattern, and is heavily used in other languages (java, rust). The idea is that the builder itself is mutable, and is used to build up an object which, when built, is immutable.

Python doesn't support multi-line chaining method calls that also look good (multiline is important, as it lets you comment parts of the build out while testing, to make sure all options work properly). Instead, you can sort of accomplish the same thing using named keyword arguments.

class Scene:
    def __init__(self, parent=None, color=None, text=None):
        self.parent = None
        self.colors = [ ]
        self.text = ""
        if parent:
            self.set_parent(parent)
        if color:
            self.add_color(color)
        if text:
            self.set_text(text)

    def set_parent(self, parent):
        self.parent = parent
        # imaginary setup
        # self.parent.register_child(self)

    def add_color(self, color):
        self.colors.append(color)

    def set_text(self, text):
        # only set text if there's text to set
        if text and text.replace(" ", ""):
            self.text = text

menu = Scene(
  parent = root,
  color = color.GREEN,
  text = "Click start!",
)
Reply
#8
I was over thinking it.
Probably because I keep jumping around with python and D.
99 percent of computer problems exists between chair and keyboard.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  a bunch of modules to import Skaperen 2 857 Nov-07-2022, 07:33 PM
Last Post: Gribouillis
  Calls to Attributes of a Class SKarimi 3 3,338 Apr-22-2021, 04:18 PM
Last Post: SKarimi
  How to use Bunch data structure moish 2 2,832 Dec-24-2020, 06:25 PM
Last Post: deanhystad
  Need help with a function that calls other functions. skurrtboi 4 2,460 Sep-30-2019, 09:28 PM
Last Post: stullis
  Testing function calls jenselme 1 2,650 Jul-25-2018, 10:33 AM
Last Post: Larz60+
  function state between calls Skaperen 5 5,083 Feb-08-2018, 02:20 AM
Last Post: Skaperen
  I am trying to copy files into a bunch of folders. tannishpage 4 3,929 Apr-22-2017, 09:36 PM
Last Post: tannishpage
  Tracing function calls PyRaider 1 3,803 Oct-25-2016, 03:44 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020