-
Notifications
You must be signed in to change notification settings - Fork 3
Code Conventions
Andrzej Pronobis edited this page Sep 4, 2017
·
12 revisions
- In Python, the default floating point type
is double precision,
implemented using C type
double
in CPython and "nearly equivalent" to Numpyfloat64
. A numpy array ofdtype=float
will usenp.float64
. Therefore, for most computations, we use the default Pythonfloat
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 usinglong
in C, and can be either 32 or 64-bit depending on the architecture. On 64-bit systems, numpy converts it tonp.int64
. Therefore, explicit 64-bit integer should be used for any computations requiring 64-bit. If 32-bit is sufficient, we use the default typeint
. 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 theNode
class can be provided. - Classes vs functions: Generators of new TensorFlow operations should be
implemented as classes (e.g.
Value
orMPEInference
). 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.