pg.symbolize

Accessible via pg.symbolize, pg.symbolic.symbolize.

symbolize(*args, **kwargs)[source]

Make a symbolic class/function out of a regular Python class/function.

pg.symbolize is introduced for the purpose of making existing classes/functions symbolically programmable. For use cases that build symbolic classes from scratch (native PyGlove classes), extending pg.Object with @pg.members that declares the symbolic properties is the recommended way, which automatically generates the __init__ method and allow symbolic attributes to be accessed via self.<member>.

pg.symbolize can be invoked as a class/function decorator, or as a function. When it is used as a decorator, the decorated class or function will be converted to a symbolic type (via pg.wrap and pg.functor_class). This is preferred when user can modify the files of existing classes/functions. For example:

@pg.symbolize
def foo(a, b):
  return a + b

f = foo(1, 2)
f.rebind(a=2)
f()           # Returns 4

@pg.symbolize([
  # (Optional) add symbolic constraint for __init__ argument 'a'.
  ('a', pg.typing.Int(min_value=0), 'Description for `a`.')
])
class Foo:
  def __init__(self, a, b):
    self._a = a
    self._b = b

  def result(self):
    return self._a + self._b

f = Foo(1, 2)
f.rebind(a=2, b=3)
f.result()   # Returns 5

When it used as a function, the input class or function will not be modified. Instead, a new symbolic type will be created and returned. This is helpful when users want to create new symbolic types from existing classes/functions without modifying their original source code. For example:

def foo(a, b):
  return a + b

# Create a new symbolic type with constraint on 'a'.
symbolic_foo = pg.symbolize(foo, [
    ('a', pg.typing.Int(min_value=0))
], returns=pg.typing.Int())
foo(1, 2)    # Returns 3 (foo is kept intact).

f = symbolic_foo(1, 2)
f.rebind(a=2)
f()          # Returns 4.

class Foo:
  def __init__(self, a, b):
    self._a = a
    self._b = b

  def result(self):
    return self._a + self._b

SymbolicFoo = pg.symbolize(Foo)
f = SymbolicFoo(2, 2)
f.rebind(a=3)
f.result()   # Returns 5.
Parameters:
  • *args

    The positional arguments for symbolize are:

    • class_or_fn: applicable when symbolize is called in function mode.

    • constraints: an optional list of tuples that allows users to specify the constraints for arguments from the __init__ method (for class) or the arguments from the function signature (for function). Each tuple should be in format:

      (<arg_name>, <value_spec>, [description], [arg_metadata])

      Where arg_name is an argument name that is acceptable to the __init__ method of the class, or the function signature; ‘value_spec’ is a pg.ValueSpec object that validates the value of the argument. description and arg_metadata are optional, for documentation and meta-programming purposes.

  • **kwargs – Keyword arguments will be passsed through to pg.wrap (for symbolizing classes) and pg.functor_class (for symbolizing functions).

Returns:

A Symbolic subclass for the decorated/input type.

Raises:

TypeError – input type cannot be symbolized, or it’s not a type.