@@ -68,16 +68,17 @@ def all_params():
6868class _Accessor (dict ):
6969 """Helper for accessing hyper-parameters."""
7070
71- def __init__ (self , root , path = None , suffix = None ):
71+ def __init__ (self , root , path = None , scope = None ):
7272 super ().__init__ ()
7373 self ._root = root
7474 self ._path = path
75- self ._suffix = suffix
75+ self ._scope = scope
7676
7777 def get_or_else (self , default : Any = None ):
7878 """Get value for the parameter, or get default value if the parameter is not defined."""
79- if self ._suffix is not None :
80- suffixes = self ._suffix .replace ("." , "#" ).split ("#" )
79+ if self ._scope is not None :
80+ suffixes = self ._scope .replace ("." , "#" ).split ("#" )
81+ _tracker .read (f"{ self ._path } @{ self ._scope } " )
8182 while suffixes :
8283 suffix = "#" .join (suffixes )
8384 full_name = f"{ self ._path } @{ suffix } "
@@ -92,22 +93,22 @@ def get_or_else(self, default: Any = None):
9293
9394 def __getattr__ (self , name : str ) -> Any :
9495 # _path and _root are not allowed as keys for user.
95- if name in ["_path" , "_root" , "_suffix " ]:
96+ if name in ["_path" , "_root" , "_scope " ]:
9697 return self [name ]
9798 return _Accessor (
9899 self ._root ,
99100 f"{ self ._path } .{ name } " if self ._path else name ,
100- suffix = self ._suffix ,
101+ scope = self ._scope ,
101102 )
102103
103104 def __setattr__ (self , name : str , value : Any ):
104105 # _path and _root are not allowed as keys for user.
105- if name in ["_path" , "_root" , "_suffix " ]:
106+ if name in ["_path" , "_root" , "_scope " ]:
106107 return self .__setitem__ (name , value )
107108 full_name = f"{ self ._path } .{ name } " if self ._path is not None else name
108109 full_name = (
109- f"{ full_name } @{ self ._suffix .replace ('.' , '#' )} "
110- if self ._suffix is not None
110+ f"{ full_name } @{ self ._scope .replace ('.' , '#' )} "
111+ if self ._scope is not None
111112 else full_name
112113 )
113114 _tracker .write (full_name )
@@ -175,7 +176,7 @@ def dynamic_dispatch(func, name=None, index=None):
175176
176177
177178class HyperParameter (dict ):
178- """HyperParameter is an extended dict with features for better parameter management .
179+ """HyperParameter is an extended dict designed for parameter storage .
179180
180181 **create and access hyper-parameters**
181182 ======================================
@@ -242,15 +243,17 @@ def put(self, name: str, value: Any) -> None:
242243
243244 Examples
244245 --------
246+
247+ 1. put parameter with simple name
245248 >>> cfg = HyperParameter()
246249 >>> cfg.put('param1', 1)
247- >>> cfg.put('obj1.propA', 'A')
248-
249- >>> cfg.param1
250- 1
250+ >>> cfg
251+ {'param1': 1}
251252
252- >>> cfg.obj1.propA
253- 'A'
253+ 2. put parameter with object-style name
254+ >>> cfg.put('obj1.propA', 'A')
255+ >>> cfg
256+ {'param1': 1, 'obj1': {'propA': 'A'}}
254257 """
255258
256259 path = name .split ("." )
@@ -307,60 +310,24 @@ def __setitem__(self, key: str, value: Any) -> None:
307310 return dict .__setitem__ (self , key , value )
308311
309312 def __getattr__ (self , name : str ) -> Any :
310- """read parameter with object-style api
311-
312- Parameters
313- ----------
314- name : str
315- parameter name
316-
317- Returns
318- -------
319- Any
320- parameter value
321-
322- Examples
323- --------
324- for simple parameters:
325- >>> hp = HyperParameter(a=1, b = {'c':2, 'd': 3})
326- >>> hp.a
327- 1
328-
329- for nested parameters:
330- >>> hp.b.c
331- 2
332-
333- >>> getattr(hp, 'b.c')
334- 2
335- """
336313 return self .get (name )
337314
338315 def __setattr__ (self , name : str , value : Any ) -> None :
339- """create/update parameter with object-style api
340-
341- Parameters
342- ----------
343- name : str
344- parameter name
345- value : Any
346- parameter value
316+ self .put (name , value )
347317
348- Examples
349- --------
350- >>> hp = HyperParameter(a=1, b = {'c':2, 'd': 3})
351- >>> hp.e = 4
318+ def __call__ (self , scope = None ) -> Any :
319+ """Return a parameter accessor.
352320
353- >>> hp['e']
354- 4
321+ This is the suggested method for accessing parameter, it supports the following features:
355322
356- >>> setattr(hp, 'A.B.C', 1)
357- >>> hp.A.B.C
358- 1
359- """
360- self .put (name , value )
323+ 1. default value for undefined parameter;
324+ 2. parameter access with named scope;
325+ 3. access tracking that records which parameter is accessed;
361326
362- def __call__ (self , suffix = None ) -> Any :
363- """Return a parameter accessor.
327+ Parameters
328+ ----------
329+ scope : str
330+ scope name, in which the accessor looks for the parameters
364331
365332 Returns
366333 -------
@@ -380,20 +347,19 @@ def __call__(self, suffix=None) -> Any:
380347 >>> cfg().b.undefined('default')
381348 'default'
382349
383- 2. hyper-parameter with suffix
384- >>> cfg(suffix ="ns").a("undefined")
350+ 2. hyper-parameter with scope
351+ >>> cfg(scope ="ns").a("undefined")
385352 1
386353
387- >>> cfg(suffix ="ns").a = 4
354+ >>> cfg(scope ="ns").a = 4
388355 >>> cfg
389356 {'a': 1, 'b': {'c': 2, 'd': 3}, 'a@ns': 4}
390357
391358 >>> cfg("ns.ns").a()
392359 4
393360 """
394361
395- suffix = dict .get (self , "#suffix#" , None ) if suffix is None else suffix
396- return _Accessor (self , suffix = suffix )
362+ return _Accessor (self , scope = scope )
397363
398364
399365class _param_scope (HyperParameter ):
@@ -452,7 +418,7 @@ def __enter__(self):
452418 def __exit__ (self , exc_type , exc_value , traceback ):
453419 _param_scope .tls .history .pop ()
454420
455- def __call__ (self , suffix = None ) -> Any :
421+ def __call__ (self , scope = None ) -> Any :
456422 """
457423 >>> @auto_param('myns.foo.params')
458424 ... def foo(a, b=2, c='c', d=None):
@@ -476,8 +442,8 @@ def __call__(self, suffix=None) -> Any:
476442 ps = {'myns': {'foo': {'params': {'b@sec1#sec2': 3}}}}
477443 1 3 c None
478444 """
479- suffix = dict .get (self , "_suffix " , None ) if suffix is None else suffix
480- return _Accessor (self , suffix = suffix )
445+ scope = dict .get (self , "_scope " , None ) if scope is None else scope
446+ return _Accessor (self , scope = scope )
481447
482448 @staticmethod
483449 def current ():
@@ -501,10 +467,10 @@ def __init__(self, index=None):
501467 def __call__ (self , * args , ** kwargs ):
502468 retval = _param_scope (* args , ** kwargs )
503469 if self ._index is not None :
504- if dict .get (retval , "_suffix " , None ) is not None :
505- retval ._suffix = f"{ retval ._suffix } #{ self ._index } "
470+ if dict .get (retval , "_scope " , None ) is not None :
471+ retval ._scope = f"{ retval ._scope } #{ self ._index } "
506472 else :
507- retval ._suffix = self ._index
473+ retval ._scope = self ._index
508474 return retval
509475
510476 def __getitem__ (self , index ):
0 commit comments