Skip to content
Andrzej Pronobis edited this page Sep 4, 2017 · 12 revisions

Code Conventions

Python

  • In Python, the default floating point type is double precision, implemented using C type double in CPython and "nearly equivalent" to Numpy float64. A numpy array of dtype=float will use np.float64. Therefore, for most computations, we use the default Python float type and assume they are of double precision.
  • We rely on the fact that in Python 3, the operator / means true division. Therefore, we do not cast integers to float explicitly. // is used for floor division.
  • In Python, the default type int is implemented using long in C, and can be either 32 or 64-bit depending on the architecture. On 64-bit systems, numpy converts it to np.int64. Therefore, explicit 64-bit integer should be used for any computations requiring 64-bit. If 32-bit is sufficient, we use the default type int. Additionally, some TensorFlow operations are more efficient for int64 (both on GPU and CPU). For GPU kernels, this is likely caused by the fact that int64 data is not stored on the GPU and therefore, for operations needing it on CPU, does not have to be sent back to host (See this SO question). As a result, in general, we should use the native type (int) unless there is a specific reason to specify int32 vs int64.
  • Getter methods vs properties: Use properties if only light processing is needed or when existing TF ops are returned. Use methods to indicate that heavier processing must be done to compute the value or when TensorFlow ops are created as a result of running the method. See Style Conventions for how to name properties and methods.
  • Properties vs attributes: Use attributes to indicate that a value can be freely modified by the user during the lifetime of the object. Use properties to indicate that an attribute should be read-only, or when there is some light processing that should be lazy and done when the property is accessed. The benefit of using attributes is less code and that the docstring for the argument of the constructor is automatically passed on to the attribute (when listed in Attributes section).
  • Functions vs methods of the Node class for graph operations: Operations running on a full graph rooted in a node should be implemented using an external function if performing the operation requires knowledge of the specific types of nodes (the operation does not apply to a generic node). Otherwise, a method of the Node class can be provided.
  • Classes vs functions: Generators of new TensorFlow operations should be implemented as classes (e.g. Value or MPEInference). Operations on the SPN graph that to not create new TensorFlow ops can be realized using simple functions (e.g. display_spn_graph(root)).
  • Prefer "protected" members, i.e. use _ prefix for most members, unless a member should clearly be private, in which case use the __ prefix. This way, it is easier to add subclasses without changing private members to protected.
Clone this wiki locally