Dynamically define attributes that depend on earlier defined attributes
I want an object that represents a path root
and an arbitrary number of subdirectories that are constructed with os.path.join(root)
. I want to access these paths with the form self.root
, self.path_a
, self.path_b
, etc... In addition to accessing them directly via self.path_a
, I want to be able to iterate over them. Unfortunately, the approach below does not allow iterating over them via attr.astuple(paths)
The first bit of code below is what I came up with. It works but feels a little hacky to me. Since this is my first use of attrs I am wondering if there is a more intuitive/idiomatic way to approach this. It took me quite a while to figure out how to write the fairly simple class below, so I thought I might be missing something obvious.
My approach
@attr.s
class Paths(object):
subdirs = attr.ib()
root = attr.ib(default=os.getcwd())
def __attrs_post_init__(self):
for name in self.subdirs:
subdir = os.path.join(self.root, name)
object.__setattr__(self, name, subdir)
def mkdirs(self):
"""Create `root` and `subdirs` if they don't already exist."""
if not os.path.isdir(self.root):
os.mkdir(self.root)
for subdir in self.subdirs:
path = self.__getattribute__(subdir)
if not os.path.isdir(path):
os.mkdir(path)
Output
>>> p = Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p
Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p.a
'/tmp/a'
>>> p.b
'/tmp/b'
>>> p.c
'/tmp/c'
The following was my first attempt, which doesn't work.
Failed attempt
@attr.s
class Paths(object):
root = attr.ib(default=os.getcwd())
subdir_1= attr.ib(os.path.join(root, 'a'))
subdir_2= attr.ib(os.path.join(root, 'b'))
Output
------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-31-71f19d55e4c3> in <module>()
1 @attr.s
----> 2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
<ipython-input-31-71f19d55e4c3> in Paths()
2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
--> 4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
6
~/miniconda3/lib/python3.6/posixpath.py in join(a, *p)
76 will be discarded. An empty last part will result in a path that
77 ends with a separator."""
--> 78 a = os.fspath(a)
79 sep = _get_sep(a)
80 path = a
TypeError: expected str, bytes or os.PathLike object, not _CountingAttr
python python-attrs
add a comment |
I want an object that represents a path root
and an arbitrary number of subdirectories that are constructed with os.path.join(root)
. I want to access these paths with the form self.root
, self.path_a
, self.path_b
, etc... In addition to accessing them directly via self.path_a
, I want to be able to iterate over them. Unfortunately, the approach below does not allow iterating over them via attr.astuple(paths)
The first bit of code below is what I came up with. It works but feels a little hacky to me. Since this is my first use of attrs I am wondering if there is a more intuitive/idiomatic way to approach this. It took me quite a while to figure out how to write the fairly simple class below, so I thought I might be missing something obvious.
My approach
@attr.s
class Paths(object):
subdirs = attr.ib()
root = attr.ib(default=os.getcwd())
def __attrs_post_init__(self):
for name in self.subdirs:
subdir = os.path.join(self.root, name)
object.__setattr__(self, name, subdir)
def mkdirs(self):
"""Create `root` and `subdirs` if they don't already exist."""
if not os.path.isdir(self.root):
os.mkdir(self.root)
for subdir in self.subdirs:
path = self.__getattribute__(subdir)
if not os.path.isdir(path):
os.mkdir(path)
Output
>>> p = Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p
Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p.a
'/tmp/a'
>>> p.b
'/tmp/b'
>>> p.c
'/tmp/c'
The following was my first attempt, which doesn't work.
Failed attempt
@attr.s
class Paths(object):
root = attr.ib(default=os.getcwd())
subdir_1= attr.ib(os.path.join(root, 'a'))
subdir_2= attr.ib(os.path.join(root, 'b'))
Output
------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-31-71f19d55e4c3> in <module>()
1 @attr.s
----> 2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
<ipython-input-31-71f19d55e4c3> in Paths()
2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
--> 4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
6
~/miniconda3/lib/python3.6/posixpath.py in join(a, *p)
76 will be discarded. An empty last part will result in a path that
77 ends with a separator."""
--> 78 a = os.fspath(a)
79 sep = _get_sep(a)
80 path = a
TypeError: expected str, bytes or os.PathLike object, not _CountingAttr
python python-attrs
This is not really whatattrs
is for. What exactly are you trying to accomplish?
– roeen30
Nov 14 '18 at 22:16
@roeen30 I made significant changes to the code examples, which I hope more clearly illustrates the problem I was trying to solve.
– truthling
Nov 15 '18 at 22:47
It is clearer what you're trying to do, but not why. Idiomatic path operations are provided by the excellentpathlib
- take a look at it if you haven't already. As the main goal ofattrs
is creating quick record classes, it doesn't really help you here, where you have a class with one pre-determined attribute (root
). Looks like trying to fit a square peg through a round hole.
– roeen30
Nov 16 '18 at 19:09
1
As a side note, if you can't avoid using__get/setattribute__()
, it is clearer to just use thegetattr()
andsetattr()
builtins.
– roeen30
Nov 16 '18 at 19:11
add a comment |
I want an object that represents a path root
and an arbitrary number of subdirectories that are constructed with os.path.join(root)
. I want to access these paths with the form self.root
, self.path_a
, self.path_b
, etc... In addition to accessing them directly via self.path_a
, I want to be able to iterate over them. Unfortunately, the approach below does not allow iterating over them via attr.astuple(paths)
The first bit of code below is what I came up with. It works but feels a little hacky to me. Since this is my first use of attrs I am wondering if there is a more intuitive/idiomatic way to approach this. It took me quite a while to figure out how to write the fairly simple class below, so I thought I might be missing something obvious.
My approach
@attr.s
class Paths(object):
subdirs = attr.ib()
root = attr.ib(default=os.getcwd())
def __attrs_post_init__(self):
for name in self.subdirs:
subdir = os.path.join(self.root, name)
object.__setattr__(self, name, subdir)
def mkdirs(self):
"""Create `root` and `subdirs` if they don't already exist."""
if not os.path.isdir(self.root):
os.mkdir(self.root)
for subdir in self.subdirs:
path = self.__getattribute__(subdir)
if not os.path.isdir(path):
os.mkdir(path)
Output
>>> p = Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p
Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p.a
'/tmp/a'
>>> p.b
'/tmp/b'
>>> p.c
'/tmp/c'
The following was my first attempt, which doesn't work.
Failed attempt
@attr.s
class Paths(object):
root = attr.ib(default=os.getcwd())
subdir_1= attr.ib(os.path.join(root, 'a'))
subdir_2= attr.ib(os.path.join(root, 'b'))
Output
------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-31-71f19d55e4c3> in <module>()
1 @attr.s
----> 2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
<ipython-input-31-71f19d55e4c3> in Paths()
2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
--> 4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
6
~/miniconda3/lib/python3.6/posixpath.py in join(a, *p)
76 will be discarded. An empty last part will result in a path that
77 ends with a separator."""
--> 78 a = os.fspath(a)
79 sep = _get_sep(a)
80 path = a
TypeError: expected str, bytes or os.PathLike object, not _CountingAttr
python python-attrs
I want an object that represents a path root
and an arbitrary number of subdirectories that are constructed with os.path.join(root)
. I want to access these paths with the form self.root
, self.path_a
, self.path_b
, etc... In addition to accessing them directly via self.path_a
, I want to be able to iterate over them. Unfortunately, the approach below does not allow iterating over them via attr.astuple(paths)
The first bit of code below is what I came up with. It works but feels a little hacky to me. Since this is my first use of attrs I am wondering if there is a more intuitive/idiomatic way to approach this. It took me quite a while to figure out how to write the fairly simple class below, so I thought I might be missing something obvious.
My approach
@attr.s
class Paths(object):
subdirs = attr.ib()
root = attr.ib(default=os.getcwd())
def __attrs_post_init__(self):
for name in self.subdirs:
subdir = os.path.join(self.root, name)
object.__setattr__(self, name, subdir)
def mkdirs(self):
"""Create `root` and `subdirs` if they don't already exist."""
if not os.path.isdir(self.root):
os.mkdir(self.root)
for subdir in self.subdirs:
path = self.__getattribute__(subdir)
if not os.path.isdir(path):
os.mkdir(path)
Output
>>> p = Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p
Paths(subdirs=['a', 'b', 'c'], root='/tmp')
>>> p.a
'/tmp/a'
>>> p.b
'/tmp/b'
>>> p.c
'/tmp/c'
The following was my first attempt, which doesn't work.
Failed attempt
@attr.s
class Paths(object):
root = attr.ib(default=os.getcwd())
subdir_1= attr.ib(os.path.join(root, 'a'))
subdir_2= attr.ib(os.path.join(root, 'b'))
Output
------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-31-71f19d55e4c3> in <module>()
1 @attr.s
----> 2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
<ipython-input-31-71f19d55e4c3> in Paths()
2 class Paths(object):
3 root = attr.ib(default=os.getcwd())
--> 4 subdir_1= attr.ib(os.path.join(root, 'a'))
5 subdir_2= attr.ib(os.path.join(root, 'b'))
6
~/miniconda3/lib/python3.6/posixpath.py in join(a, *p)
76 will be discarded. An empty last part will result in a path that
77 ends with a separator."""
--> 78 a = os.fspath(a)
79 sep = _get_sep(a)
80 path = a
TypeError: expected str, bytes or os.PathLike object, not _CountingAttr
python python-attrs
python python-attrs
edited Nov 16 '18 at 18:06
truthling
asked Nov 14 '18 at 22:12
truthlingtruthling
407
407
This is not really whatattrs
is for. What exactly are you trying to accomplish?
– roeen30
Nov 14 '18 at 22:16
@roeen30 I made significant changes to the code examples, which I hope more clearly illustrates the problem I was trying to solve.
– truthling
Nov 15 '18 at 22:47
It is clearer what you're trying to do, but not why. Idiomatic path operations are provided by the excellentpathlib
- take a look at it if you haven't already. As the main goal ofattrs
is creating quick record classes, it doesn't really help you here, where you have a class with one pre-determined attribute (root
). Looks like trying to fit a square peg through a round hole.
– roeen30
Nov 16 '18 at 19:09
1
As a side note, if you can't avoid using__get/setattribute__()
, it is clearer to just use thegetattr()
andsetattr()
builtins.
– roeen30
Nov 16 '18 at 19:11
add a comment |
This is not really whatattrs
is for. What exactly are you trying to accomplish?
– roeen30
Nov 14 '18 at 22:16
@roeen30 I made significant changes to the code examples, which I hope more clearly illustrates the problem I was trying to solve.
– truthling
Nov 15 '18 at 22:47
It is clearer what you're trying to do, but not why. Idiomatic path operations are provided by the excellentpathlib
- take a look at it if you haven't already. As the main goal ofattrs
is creating quick record classes, it doesn't really help you here, where you have a class with one pre-determined attribute (root
). Looks like trying to fit a square peg through a round hole.
– roeen30
Nov 16 '18 at 19:09
1
As a side note, if you can't avoid using__get/setattribute__()
, it is clearer to just use thegetattr()
andsetattr()
builtins.
– roeen30
Nov 16 '18 at 19:11
This is not really what
attrs
is for. What exactly are you trying to accomplish?– roeen30
Nov 14 '18 at 22:16
This is not really what
attrs
is for. What exactly are you trying to accomplish?– roeen30
Nov 14 '18 at 22:16
@roeen30 I made significant changes to the code examples, which I hope more clearly illustrates the problem I was trying to solve.
– truthling
Nov 15 '18 at 22:47
@roeen30 I made significant changes to the code examples, which I hope more clearly illustrates the problem I was trying to solve.
– truthling
Nov 15 '18 at 22:47
It is clearer what you're trying to do, but not why. Idiomatic path operations are provided by the excellent
pathlib
- take a look at it if you haven't already. As the main goal of attrs
is creating quick record classes, it doesn't really help you here, where you have a class with one pre-determined attribute (root
). Looks like trying to fit a square peg through a round hole.– roeen30
Nov 16 '18 at 19:09
It is clearer what you're trying to do, but not why. Idiomatic path operations are provided by the excellent
pathlib
- take a look at it if you haven't already. As the main goal of attrs
is creating quick record classes, it doesn't really help you here, where you have a class with one pre-determined attribute (root
). Looks like trying to fit a square peg through a round hole.– roeen30
Nov 16 '18 at 19:09
1
1
As a side note, if you can't avoid using
__get/setattribute__()
, it is clearer to just use the getattr()
and setattr()
builtins.– roeen30
Nov 16 '18 at 19:11
As a side note, if you can't avoid using
__get/setattribute__()
, it is clearer to just use the getattr()
and setattr()
builtins.– roeen30
Nov 16 '18 at 19:11
add a comment |
2 Answers
2
active
oldest
votes
First attempt: you can't just attach random data to the class and hope that attrs (in this case astuple) will pick it up. attrs specifically tries to avoid magic and guessing, which means that you have to indeed define your attributes on the class.
Second attempt: you cannot use attribute name in the class scope (i.e. within class Paths:
but outside of a method because – as Python tells you – at this point they are still internal data that is used by @attr.s
.
The most elegant approach I can think of is a generic factory that takes the path as an argument and builds the full path:
In [1]: import attr
In [2]: def make_path_factory(path):
...: def path_factory(self):
...: return os.path.join(self.root, path)
...: return attr.Factory(path_factory, takes_self=True)
Which you can use like this:
In [7]: @attr.s
...: class C(object):
...: root = attr.ib()
...: a = attr.ib(make_path_factory("a"))
...: b = attr.ib(make_path_factory("b"))
In [10]: C("/tmp")
Out[10]: C(root='/tmp', a='/tmp/a', b='/tmp/b')
In [11]: attr.astuple(C("/tmp"))
Out[11]: ('/tmp', '/tmp/a', '/tmp/b')
attrs being attrs, you can of course go further and define your own attr.ib wrapper:
In [12]: def path(p):
...: return attr.ib(make_path_factory(p))
In [13]: @attr.s
...: class D(object):
...: root = attr.ib()
...: a = path("a")
...: b = path("b")
...:
In [14]: D("/tmp")
Out[14]: D(root='/tmp', a='/tmp/a', b='/tmp/b')
add a comment |
Can't guess why would you like to access as self.paths.path
. But, here is what i'd do:
class D(object):
root = os.getcwd()
paths = dict()
def __init__(self, paths=):
self.paths.update('root': self.root)
for path in paths:
self.paths.update(path: os.path.join(self.root, path))
def __str__(self):
return str(self.paths)
d = D(paths=['static', 'bin', 'source'])
print(d)
print(d.paths['bin'])
output
'root': '/home/runner', 'static': '/home/runner/static', 'bin': '/home/runner/bin', 'source': '/home/runner/source'
/home/runner/bin
You can make this more complex. Just an example. Hope it helps.
1
That would do the trick, but I'm interested in starting to use attrs.
– truthling
Nov 15 '18 at 22:48
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53309516%2fdynamically-define-attributes-that-depend-on-earlier-defined-attributes%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
First attempt: you can't just attach random data to the class and hope that attrs (in this case astuple) will pick it up. attrs specifically tries to avoid magic and guessing, which means that you have to indeed define your attributes on the class.
Second attempt: you cannot use attribute name in the class scope (i.e. within class Paths:
but outside of a method because – as Python tells you – at this point they are still internal data that is used by @attr.s
.
The most elegant approach I can think of is a generic factory that takes the path as an argument and builds the full path:
In [1]: import attr
In [2]: def make_path_factory(path):
...: def path_factory(self):
...: return os.path.join(self.root, path)
...: return attr.Factory(path_factory, takes_self=True)
Which you can use like this:
In [7]: @attr.s
...: class C(object):
...: root = attr.ib()
...: a = attr.ib(make_path_factory("a"))
...: b = attr.ib(make_path_factory("b"))
In [10]: C("/tmp")
Out[10]: C(root='/tmp', a='/tmp/a', b='/tmp/b')
In [11]: attr.astuple(C("/tmp"))
Out[11]: ('/tmp', '/tmp/a', '/tmp/b')
attrs being attrs, you can of course go further and define your own attr.ib wrapper:
In [12]: def path(p):
...: return attr.ib(make_path_factory(p))
In [13]: @attr.s
...: class D(object):
...: root = attr.ib()
...: a = path("a")
...: b = path("b")
...:
In [14]: D("/tmp")
Out[14]: D(root='/tmp', a='/tmp/a', b='/tmp/b')
add a comment |
First attempt: you can't just attach random data to the class and hope that attrs (in this case astuple) will pick it up. attrs specifically tries to avoid magic and guessing, which means that you have to indeed define your attributes on the class.
Second attempt: you cannot use attribute name in the class scope (i.e. within class Paths:
but outside of a method because – as Python tells you – at this point they are still internal data that is used by @attr.s
.
The most elegant approach I can think of is a generic factory that takes the path as an argument and builds the full path:
In [1]: import attr
In [2]: def make_path_factory(path):
...: def path_factory(self):
...: return os.path.join(self.root, path)
...: return attr.Factory(path_factory, takes_self=True)
Which you can use like this:
In [7]: @attr.s
...: class C(object):
...: root = attr.ib()
...: a = attr.ib(make_path_factory("a"))
...: b = attr.ib(make_path_factory("b"))
In [10]: C("/tmp")
Out[10]: C(root='/tmp', a='/tmp/a', b='/tmp/b')
In [11]: attr.astuple(C("/tmp"))
Out[11]: ('/tmp', '/tmp/a', '/tmp/b')
attrs being attrs, you can of course go further and define your own attr.ib wrapper:
In [12]: def path(p):
...: return attr.ib(make_path_factory(p))
In [13]: @attr.s
...: class D(object):
...: root = attr.ib()
...: a = path("a")
...: b = path("b")
...:
In [14]: D("/tmp")
Out[14]: D(root='/tmp', a='/tmp/a', b='/tmp/b')
add a comment |
First attempt: you can't just attach random data to the class and hope that attrs (in this case astuple) will pick it up. attrs specifically tries to avoid magic and guessing, which means that you have to indeed define your attributes on the class.
Second attempt: you cannot use attribute name in the class scope (i.e. within class Paths:
but outside of a method because – as Python tells you – at this point they are still internal data that is used by @attr.s
.
The most elegant approach I can think of is a generic factory that takes the path as an argument and builds the full path:
In [1]: import attr
In [2]: def make_path_factory(path):
...: def path_factory(self):
...: return os.path.join(self.root, path)
...: return attr.Factory(path_factory, takes_self=True)
Which you can use like this:
In [7]: @attr.s
...: class C(object):
...: root = attr.ib()
...: a = attr.ib(make_path_factory("a"))
...: b = attr.ib(make_path_factory("b"))
In [10]: C("/tmp")
Out[10]: C(root='/tmp', a='/tmp/a', b='/tmp/b')
In [11]: attr.astuple(C("/tmp"))
Out[11]: ('/tmp', '/tmp/a', '/tmp/b')
attrs being attrs, you can of course go further and define your own attr.ib wrapper:
In [12]: def path(p):
...: return attr.ib(make_path_factory(p))
In [13]: @attr.s
...: class D(object):
...: root = attr.ib()
...: a = path("a")
...: b = path("b")
...:
In [14]: D("/tmp")
Out[14]: D(root='/tmp', a='/tmp/a', b='/tmp/b')
First attempt: you can't just attach random data to the class and hope that attrs (in this case astuple) will pick it up. attrs specifically tries to avoid magic and guessing, which means that you have to indeed define your attributes on the class.
Second attempt: you cannot use attribute name in the class scope (i.e. within class Paths:
but outside of a method because – as Python tells you – at this point they are still internal data that is used by @attr.s
.
The most elegant approach I can think of is a generic factory that takes the path as an argument and builds the full path:
In [1]: import attr
In [2]: def make_path_factory(path):
...: def path_factory(self):
...: return os.path.join(self.root, path)
...: return attr.Factory(path_factory, takes_self=True)
Which you can use like this:
In [7]: @attr.s
...: class C(object):
...: root = attr.ib()
...: a = attr.ib(make_path_factory("a"))
...: b = attr.ib(make_path_factory("b"))
In [10]: C("/tmp")
Out[10]: C(root='/tmp', a='/tmp/a', b='/tmp/b')
In [11]: attr.astuple(C("/tmp"))
Out[11]: ('/tmp', '/tmp/a', '/tmp/b')
attrs being attrs, you can of course go further and define your own attr.ib wrapper:
In [12]: def path(p):
...: return attr.ib(make_path_factory(p))
In [13]: @attr.s
...: class D(object):
...: root = attr.ib()
...: a = path("a")
...: b = path("b")
...:
In [14]: D("/tmp")
Out[14]: D(root='/tmp', a='/tmp/a', b='/tmp/b')
answered Nov 16 '18 at 12:16
hynekhynek
1,30211018
1,30211018
add a comment |
add a comment |
Can't guess why would you like to access as self.paths.path
. But, here is what i'd do:
class D(object):
root = os.getcwd()
paths = dict()
def __init__(self, paths=):
self.paths.update('root': self.root)
for path in paths:
self.paths.update(path: os.path.join(self.root, path))
def __str__(self):
return str(self.paths)
d = D(paths=['static', 'bin', 'source'])
print(d)
print(d.paths['bin'])
output
'root': '/home/runner', 'static': '/home/runner/static', 'bin': '/home/runner/bin', 'source': '/home/runner/source'
/home/runner/bin
You can make this more complex. Just an example. Hope it helps.
1
That would do the trick, but I'm interested in starting to use attrs.
– truthling
Nov 15 '18 at 22:48
add a comment |
Can't guess why would you like to access as self.paths.path
. But, here is what i'd do:
class D(object):
root = os.getcwd()
paths = dict()
def __init__(self, paths=):
self.paths.update('root': self.root)
for path in paths:
self.paths.update(path: os.path.join(self.root, path))
def __str__(self):
return str(self.paths)
d = D(paths=['static', 'bin', 'source'])
print(d)
print(d.paths['bin'])
output
'root': '/home/runner', 'static': '/home/runner/static', 'bin': '/home/runner/bin', 'source': '/home/runner/source'
/home/runner/bin
You can make this more complex. Just an example. Hope it helps.
1
That would do the trick, but I'm interested in starting to use attrs.
– truthling
Nov 15 '18 at 22:48
add a comment |
Can't guess why would you like to access as self.paths.path
. But, here is what i'd do:
class D(object):
root = os.getcwd()
paths = dict()
def __init__(self, paths=):
self.paths.update('root': self.root)
for path in paths:
self.paths.update(path: os.path.join(self.root, path))
def __str__(self):
return str(self.paths)
d = D(paths=['static', 'bin', 'source'])
print(d)
print(d.paths['bin'])
output
'root': '/home/runner', 'static': '/home/runner/static', 'bin': '/home/runner/bin', 'source': '/home/runner/source'
/home/runner/bin
You can make this more complex. Just an example. Hope it helps.
Can't guess why would you like to access as self.paths.path
. But, here is what i'd do:
class D(object):
root = os.getcwd()
paths = dict()
def __init__(self, paths=):
self.paths.update('root': self.root)
for path in paths:
self.paths.update(path: os.path.join(self.root, path))
def __str__(self):
return str(self.paths)
d = D(paths=['static', 'bin', 'source'])
print(d)
print(d.paths['bin'])
output
'root': '/home/runner', 'static': '/home/runner/static', 'bin': '/home/runner/bin', 'source': '/home/runner/source'
/home/runner/bin
You can make this more complex. Just an example. Hope it helps.
answered Nov 15 '18 at 2:24
ChecheCheche
813219
813219
1
That would do the trick, but I'm interested in starting to use attrs.
– truthling
Nov 15 '18 at 22:48
add a comment |
1
That would do the trick, but I'm interested in starting to use attrs.
– truthling
Nov 15 '18 at 22:48
1
1
That would do the trick, but I'm interested in starting to use attrs.
– truthling
Nov 15 '18 at 22:48
That would do the trick, but I'm interested in starting to use attrs.
– truthling
Nov 15 '18 at 22:48
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53309516%2fdynamically-define-attributes-that-depend-on-earlier-defined-attributes%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
This is not really what
attrs
is for. What exactly are you trying to accomplish?– roeen30
Nov 14 '18 at 22:16
@roeen30 I made significant changes to the code examples, which I hope more clearly illustrates the problem I was trying to solve.
– truthling
Nov 15 '18 at 22:47
It is clearer what you're trying to do, but not why. Idiomatic path operations are provided by the excellent
pathlib
- take a look at it if you haven't already. As the main goal ofattrs
is creating quick record classes, it doesn't really help you here, where you have a class with one pre-determined attribute (root
). Looks like trying to fit a square peg through a round hole.– roeen30
Nov 16 '18 at 19:09
1
As a side note, if you can't avoid using
__get/setattribute__()
, it is clearer to just use thegetattr()
andsetattr()
builtins.– roeen30
Nov 16 '18 at 19:11