Forum Archive

Viewing Definitions

SithMauls

I've been using Pythonista for about a week now; primarily as a learning tool while I'm on the go. With that in mind, my terminology might be a little off so I apologise if I sound like I have no idea what I'm talking about.

Basically, I've been playing around with making little 2D games with the app and I want to delve into some of the functions a bit more. I was hoping to be able to see some of the definitions for functions so I can get a glimpse of how they perform. I'd also like to implement my own action functions similar to "move_to" and "rotate_by".

Is it possible to view these definitions somewhere? Either within the app or online etc. I believe Visual Studio allows you to highlight a function call and right-click to view its definition but I'm struggling to find anything similar in Pythonista.

Any help would be much appreciated! :)

ccc

If you click on the title of the file at the top of the editor, you will get a popup menu of all functions in that file.

If you tap and hold on a standard library function name in the editor and then select 'help', you will be taken to the Python docs.

SithMauls

Thanks for taking the time to reply. Sadly, I don't think I've worded myself very well so I'll try specifying a bit more carefully.

In the Scene module, there are Action objects with methods such as "move_to" and "rotate_by", I'd like to be able to view the code that defines these built-in methods so I can get a better understanding of them.

So I'm assuming there's code somewhere within the app under the Action class that includes a function definition beginning "def move_to(x, y[, duration, timing_mode])" and containing the code which is executed when this method is called.

I might have my assumptions wrong, or this code might be inaccessible to view, so apologies if I'm asking a silly question. Viewing the definitions for built-in methods would just be quite convenient for me, as a learner, to better understand how things work.

dgelessus

Short version: It depends on the function - for some functions you can see the source code easily, for others it takes some work, and sometimes it's not possible at all. For the methods of scene.Action, you cannot see the source code at all.

Long version: In Python there are two types of functions:

  1. Python functions (type function aka types.FunctionType), which are functions that were written in Python code using a def or lambda. If you print out a Python function, it looks like <function python_func at 0x596f752077696e21>. Because they are written in Python, the source file and code can usually be found automatically using the inspect.getsourcefile and inspect.getsource functions. If the source code doesn't exist for some reason, you can at least use dis.dis to disassemble the Python bytecode - which is much less readable than normal Python code, but not impossible to understand.
  2. "Built-in" functions (type builtin_function_or_method aka types.BuiltInFunctionType aka types.BuiltInMethodType), which are functions that were implemented in a language that compiles to native code, usually C, C++, Objective-C, or assembly. If you print out a built-in function, it looks like <built-in function builtin_func>. Because they are written in a compiled language, the source code is not needed or available at runtime. If the function is from an open source library (such as CPython itself, numpy, or Pillow), you can search for the source code there, however you need to do this by hand. For functions from a closed source library (such as Pythonista's own modules) this is not possible of course.

Note that very few libraries are pure native code. Many libraries are written in both Python and native code, usually split into a public Python and an internal native module. You can see this with scene: The main scene module that you get with import scene is actually written in Python (see Modules & Templates > Standard Library (3.5) > site-packages > scene.py), but it imports many classes and functions from an internal _scene2 module that is written in (Objective-)C. This means that you can see the source code for the parts of scene that are written in Python, but not the parts written in (Objective-)C.

enceladus

If your aim is to implement your own actions, you can use update or custom_action. Here is an example that implements move_to action using either update or custom_action.

# action move_to example
import scene  

class MyScene(scene.Scene):
    def setup(self):
        self.label_node = scene.LabelNode('A',
                    position=(100,400), parent=self)
        self.animate_action = scene.Action.move_to(340, 400, 2)

    def touch_ended(self, touch):
        self.label_node.run_action(self.animate_action)

scene.run(MyScene())

'''
# action move_to example implemented using update
import scene  

class MyScene(scene.Scene):
    def setup(self):
        self.label_node = scene.LabelNode('A',
                    position=(100,400), parent=self)
        #self.animate_action = scene.Action.move_to(340, 400, 2)
        self.start_flag = False

    def update(self):
        if self.start_flag:
            x,y = self.label_node.position
            if x < 340:
                self.label_node.position = (x+2, y)
            else:
                self.start_flag = False

    def touch_ended(self, touch):
        self.start_flag = True
        #self.label_node.run_action(self.animate_action)

scene.run(MyScene())
'''


'''
# action move_to example implemented using custom_action
import scene  

def custom_action(node, progress):
    x,y = node.initial_position
    node.position = (x+240*progress, y)

class MyScene(scene.Scene):
    def setup(self):
        self.label_node = scene.LabelNode('A',
                    position=(100,400), parent=self)
        x,y = self.label_node.position
        self.label_node.initial_position = (x,y)
        self.animate_action = scene.Action.call(custom_action, 2)

    def touch_ended(self, touch):
        self.label_node.run_action(self.animate_action)

scene.run(MyScene())
'''







SithMauls

@enceladus Thanks for the in-depth reply! I quite like the custom_action implementation, I'm just playing around with it now and wondered if it was possible to add parameters to the custom actions. I can get a custom action to function if it takes no parameters, but I'm struggling with ones that do take parameters.

As an example, I have a function which rotates one object around another by a specified amount of degrees:

    def rotate_around(self, point, centre, angle):
        p = point.position #point
        c = centre.position #centre
        a = ((angle)*(math.pi/180)) #angle

        x = math.cos(a)*(p.x-c.x)-math.sin(a)*(p.y-c.y)+c.x
        y = math.sin(a)*(p.x-c.x)+math.cos(a)*(p.y-c.y)+c.y
        point.position = (x,y)

How would I go about translating this into a custom action so that it could be used in a sequence or group etc?

Again, thanks for the help! :)

SithMauls

@dgelessus Thanks for being so thorough in your answer. I'd read somewhere that source code is often split between various languages and compiled differently, but your answer has cleared up a few things for me. That scene.py file is also interesting to look at; thanks for pointing me to it :)

enceladus

You can not add extra parameters to custom_action but you can put the desired information in the node. In the example, initial_position is the information passed to custom_action.

enceladus

Look at the Animation class in the scene_drawing.py. Action implementation is similar to that. (Scene_drawing.py is the old implementation . It is there mainly for compatibility with old scene code)

SithMauls

@enceladus Thank you! I was trying to create an enemy movement that spiralled toward the centre of the screen and I've finally cracked it with the help from the replies in this post! :)

Much appreciated! I'm delighted!