-
Notifications
You must be signed in to change notification settings - Fork 880
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
new feature: AgentSet.get can retrieve one or more then one attribute #2044
Changes from 2 commits
a510b34
cb78523
22cd104
5f96227
76bb633
c0660a4
c441910
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ | |
from random import Random | ||
|
||
# mypy | ||
from typing import TYPE_CHECKING, Any, Callable | ||
from typing import TYPE_CHECKING, Any, Callable, List | ||
|
||
if TYPE_CHECKING: | ||
# We ensure that these are not imported during runtime to prevent cyclic | ||
|
@@ -264,17 +264,24 @@ def do( | |
|
||
return res if return_results else self | ||
|
||
def get(self, attr_name: str) -> list[Any]: | ||
def get(self, attr_names: str | list[str]) -> list[Any]: | ||
""" | ||
Retrieve a specified attribute from each agent in the AgentSet. | ||
Retrieve the specified attribute(s) from each agent in the AgentSet. | ||
|
||
Args: | ||
attr_name (str): The name of the attribute to retrieve from each agent. | ||
attr_names (str | List[str]): The name(s) of the attribute(s) to retrieve from each agent. | ||
|
||
Returns: | ||
list[Any]: A list of attribute values from each agent in the set. | ||
list[Any]: A list of attribute values for each agent in the set. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this still correct? Would it be nested in some sort when a list of attrs is inputted? Maybe make a little bit more explicit what is returned when a str is inputted for attr_names, and what when a list of strings is inputted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see the updated text |
||
""" | ||
return [getattr(agent, attr_name) for agent in self._agents] | ||
|
||
if isinstance(attr_names, str): | ||
return [getattr(agent, attr_names) for agent in self._agents] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should default to None (getattr(agent, attr_names, None)). This way it would be easier to collect across different agent types, which might or might not have the specified attributes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see your point but I am torn. I personally probably would prefer getting the error explicitly rather than being confronted with None values downstream. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Past discussion: projectmesa/mesa-examples#90. The summary is that it depends on the coder's background: in JavaScript, it is not surprising for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could add a boolean switch (something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that would make the code internally more complicated. You would get two additional nested if/else. The easier solution is for the user to do agentset.select("condition to ensure attribute exists").get(). Also, why allow None in the first place? It only gives more downstream problems. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think its not necesarily an "error" if we collect None instead of triggering an AttributeError. It depends on the use case. If you quickly want to get some attributes on all of your agents, but some agents don't have that attribute you still get some result. Otherwise you first have to pre-select the right AgentSet and then collect the attributes. I think the cleanest solution would probably be to mimic getattr in that users can provide a default value for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. implementation wise this is a bit tricky. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can defer this discussion and implementation in a separate PR. The current behavior in this PR is consistent with the existing API, which does not fall back to |
||
else: | ||
return [ | ||
[getattr(agent, attr_name) for attr_name in attr_names] | ||
for agent in self._agents | ||
] | ||
|
||
def __getitem__(self, item: int | slice) -> Agent: | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
List
here shouldn't be capitalized.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value also has a capitalized
List
. This may be a small typo, but it can't be automatically fixed bypyupgrade
.