• Re: Is Lexical Binding The Norm Yet?

    From Stefan Ram@21:1/5 to Stefan Ram on Sun Jan 21 07:28:12 2024
    Newsgroups: comp.lang.python

    [email protected] (Stefan Ram) writes:
    from types import *

    What do you mean, the cloning part is missing?

    import types

    # create a new object
    def counter_object(): pass

    # attach a numeric field to the object
    counter_object.counter_value = 0

    # define a named function
    def increment_value( self ): self.counter_value += 1

    # attach the named function to the object as a method counter_object.increment_value = \
    types.MethodType( increment_value, counter_object )

    # call the method
    counter_object.increment_value()

    # attach an unnamed function to the object
    counter_object.get_value = \
    types.MethodType( lambda self: self.counter_value, counter_object )

    # call that method
    # Prints "1".
    print( counter_object.get_value() )

    # An ad-hoc function to clone an object for the purpose of "prototype
    # inheritance". Might need to be refined for more general uses.
    def clone_object( object_ ):
    def new_object(): pass
    for attribute in dir( object_ ):
    if attribute[ :2 ]!= '__':
    if type( getattr( object_, attribute ))== types.MethodType:
    method = getattr( object_, attribute )
    function = types.FunctionType( method.__code__, {} )
    method = types.MethodType( function, new_object )
    setattr( new_object, attribute, method )
    else:
    field = getattr( object_, attribute )
    setattr( new_object, attribute, field )
    return new_object

    # create two "clones" ("clone objects")
    clone = clone_object( counter_object )
    other = clone_object( counter_object )

    # The clones "inherited" the counter field including its value.
    # Prints "1 1 1".
    print( counter_object.get_value(), clone.get_value(), other.get_value() )

    # Each object's counter has a value independent from the other object's
    # counter.
    other.increment_value()

    # Prints "1 1 2"
    print( counter_object.get_value(), clone.get_value(), other.get_value() )

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Stefan Ram on Sun Jan 21 17:27:09 2024
    [email protected] (Stefan Ram) writes:
    What do you mean, the cloning part is missing?

    Most standard functions do not call the custom dunder methods
    of our prototype-based objects. Yes, the standard library was
    written for class-based objects ("3.3.12 Special method lookup")!

    However, if you just need few staples such as "str" and "print",
    you can define them yourself. (The standard library will not
    use them, but you can call them in your own code.)

    import types

    # a custom global str functions for prototype objects
    # used below
    def str( x ): return x.__str__()

    # a custom global print functions for prototype objects
    # used below
    std_print = print
    def print( *args, **kwargs ):
    return std_print( *( arg.__str__() for arg in args ), **kwargs )

    # create a new object
    def counter_object(): pass

    # attach a numeric field to the object
    counter_object.counter_value = 0

    # define a named function
    def increment_value( self ): self.counter_value += 1

    # attach the named function to the object as a method counter_object.increment_value = \
    types.MethodType( increment_value, counter_object )

    # call the method
    counter_object.increment_value()

    # attach an unnamed function to the object
    counter_object.get_value = \
    types.MethodType( lambda self: self.counter_value, counter_object )

    # attach an unnamed function to the object
    counter_object.__str__ = \
    types.MethodType\
    ( lambda self: str( self.counter_value ), counter_object )

    # call that method
    # Prints "1".
    print( counter_object.get_value() )

    # An ad-hoc function to clone an object for the purpose of "prototype
    # inheritance". Might need to be refined for more general uses.
    def clone_object( object_ ):
    def new_object(): pass
    for attribute in dir( object_ ):
    if attribute[ :2 ]!= '__' or attribute in[ '__str__' ]:
    if type( getattr( object_, attribute ))== types.MethodType:
    method = getattr( object_, attribute )
    function = types.FunctionType\
    ( method.__code__, globals() )
    method = types.MethodType( function, new_object )
    setattr( new_object, attribute, method )
    else:
    field = getattr( object_, attribute )
    setattr( new_object, attribute, field )
    return new_object

    # create two "clones" ("clone objects")
    clone = clone_object( counter_object )
    other = clone_object( counter_object )

    # The clones "inherited" the counter field including its value.
    # Prints "1 1 1".
    print( counter_object.get_value(), clone.get_value(), other.get_value() )

    # Each object's counter has a value independent from the other
    # object's counter.
    other.increment_value()

    # Prints "1 1 2"
    print( counter_object.get_value(), clone.get_value(), other.get_value() )

    # Prints "1 1 2"
    print( str( counter_object ), str( clone ), str( other ))

    # Prints "1 1 2"
    print( counter_object, clone, other )

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Stefan Ram on Sun Jan 21 17:37:51 2024
    [a multipost, as an exception]

    [email protected] (Stefan Ram) writes:
    the Python standard library assumes class-based objects.)

    Since the thread is about "binding": Python can be very
    explicit when it comes to binding (should you need it).

    main.py

    import types

    x = 2

    def f():
    return x

    # prints "2"
    print( f() )

    g = types.FunctionType( f.__code__, { 'x': 4 } )

    # prints "4"
    print( g() )

    h = types.FunctionType( f.__code__, globals() )

    # prints "2"
    print( h() )

    def a():
    x = 3

    # prints "2"
    print( f() )

    # prints "3"
    print( types.FunctionType( f.__code__, locals() )() )

    # prints "2"
    print( types.FunctionType( f.__code__, globals() )() )

    a()

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)