Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6038187
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T06:10:55+00:00 2026-05-23T06:10:55+00:00

I haven’t seen an established way to memoize a function that takes key-word arguments,

  • 0

I haven’t seen an established way to memoize a function that takes key-word arguments, i.e. something of type

def f(*args, **kwargs)

since typically a memoizer has a dict to cache results for a given set of input parameters, and kwargs is a dict and hence unhashable. I have tried, following discussions here, using

(args, frozenset(kwargs.items()))

as key to the cache dict, but this only works if the values in kwargs are hashable. Furthermore, as pointed out in answers below is that frozenset is not an ordered data structure. Therefore this solution might be safer:

(args, tuple(sorted(kwargs.items())))

But it still cannot cope with un-hashable elements. Another approach I have seen is to use a string representation of the kwargs in the cache key:

(args, str(sorted(kwargs.items())))

The only drawback I see with this is the overhead of hashing a potentially very long string. As far as I can see the results should be correct. Can anyone spot any problems with the latter approach? One of the answers below points out that this assumes certain behaviour of the __str__ or __repr__ functions for the values of the key-word arguments. This seems like a show-stopper.

Is there another, more established way of achieving memoization that can cope with **kwargs and un-hashable argument values?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T06:10:55+00:00Added an answer on May 23, 2026 at 6:10 am
    key = (args, frozenset(kwargs.items()))
    

    This is the "best" you can do without making assumptions about your data.

    However it seems conceivable to want to perform memoization on dictionaries (a bit unusual though), you could special-case that if you desired it. For example you could recursively apply frozenset(---.items()) while copying dictionaries.


    If you do sorted, you could be in a bad situation where you have unorderable keys. For example, "The subset and equality comparisons do not generalize to a complete ordering function. For example, any two disjoint sets are not equal and are not subsets of each other, so all of the following return False: a<b, a==b, or a>b. Accordingly, sets do not implement the cmp() method."

    >>> sorted([frozenset({1,2}), frozenset({1,3})])
    [frozenset({1, 2}), frozenset({1, 3})]
    
    >>> sorted([frozenset({1,3}), frozenset({1,2})]) # THE SAME
    [frozenset({1, 3}), frozenset({1, 2})] # DIFFERENT SORT RESULT
    
    # sorted(stuff) != sorted(reversed(stuff)), if not strictly totally ordered
    

    edit: Ignacio says "While you can’t use sorted() on arbitrary dicts, kwargs will have str keys." This is entirely correct. Thus this is not an issue for keys, though possibly something to keep in mind for values if you (or unlikely repr) are relying on sorting somehow.


    Regarding using str:

    It is the case most data will work nicely, but it is possible for an adversary (e.g. in a security-vulnerability context) to craft a collision. It’s not easy mind you because most default reprs use lots of good grouping and escape. In fact I was not able to find such a collision. But it is possible with sloppy third-party or incomplete repr implementations.


    Also consider the following: If you are storing keys like ((<map object at 0x1377d50>,), frozenset(...)) and ((<list_iterator object at 0x1377dd0>,<list_iterator object at 0x1377dd0>), frozenset(...)), your cache will grow unboundedly just by calling the same items. (You could perhaps work around this issue with a regex…) And attempting to consume the generators will mess up the semantics of the function you’re using. This may be desired behavior though if you wish to memoize on is-style equality rather than ==-style equality.

    Also doing something like str({1:object()}) in the interpreter will return an object at the same location in memory each time! I think this is the garbage collector at work. This would be disastrous, because if you happen to be hashing <some object at 0x???????> and you happen to create an object of the same type at the same memory location later on (due to garbage collection), you will get incorrect results from the memoized function. As mentioned, one possibly really hackish workaround is to detect such objects with a regex.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Haven't seen anything, but I have seen that you can create albums in the
Haven't found in docs. Does java ResultSet supports query arguments,like jdbcTemplate? For example, something
Haven't seen this feature anywhere else. I know that the 32nd bit is used
Haven't seen many Geneva related questions yet, I have posted this question in the
Haven't seen anything about it here but it seems to solve one of the
I haven't seen any questions relating to GNU autoconf/automake builds, but I'm hoping at
I haven't seen this question anywhere else, I hope someone can help. I have
I haven't found any documentation on this or seen this done before, but is
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
Haven't found this in my search on Stackoverflow - I know I've seen a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.