Question: What is the most pythonic and correct way of doing composition aliases? Here's a hypothetical scenario: class House: def cleanup(self, arg1, arg2, kwarg1=False): # do something class Person: def __init__(self, house): self.house = house # aliases house.cleanup # 1. self.cleanup_house = self.house.cleanup # 2. def cleanup_house(self, arg1, arg2, kwarg1=False): return self.house.cleanup(arg1=arg1, arg2=arg2, kwarg1=kwarg1)  AFAIK with #1 my tested editors understand these just as fine as #2 - auto completion, doc strings etc.  Are there any down-sides to #1 approach? Which way is more correct from python's point of view? To expand on method #1 unsettable and type hinted variant would be immune to all of the issues pointed out in the comments: class House: def cleanup(self, arg1, arg2, kwarg1=False): """clean house is nice to live in!""" pass class Person: def __init__(self, house: House): self._house = house # aliases self.cleanup_house = self.house.cleanup @property def house(self): return self._house 

Answer: There are a number of problems with the first method:  The alias won't update when the attribute it refers to changes unless you jump through extra hoops. You could, for example, make house a property with a setter, but that is non-trivial work for something that shouldn't require it. See the end of this answer for a sample implementation. cleanup_house will not be inheritable. A function object defined in a class is a non-data descriptor that can be inherited and overridden, as well as be bound to an instance. An instance attribute like in the first approach is not present in the class at all. The fact that it is a bound method is incidental. A child class will not be able to access super().cleanup_house, for a concrete example. person.cleanup_house.__name__ != 'cleanup_house'. This is not something you check often, but when you do, you would expect the function name to be cleanup.  The good news is that you don't have to repeat signatures multiple times to use approach #2. Python offers the very convenient splat (*)/splatty-splat (**) notation for delegating all argument checking to the method being wrapped: def cleanup_house(self, *args, **kwargs): return self.house.cleanup(*args, **kwargs)  And that's it. All regular and default arguments are passed through as-is. This is the reason that #2 is by far the more pythonic approach. I have no idea how it will interact with editors that support type hints unless you copy the method signature. One thing that may be a problem is that cleanup_house.__doc__ is not the same as house.cleanup.__doc__. This could potentially merit a conversion of house to a property, whose setter assigns cleanup_house.__doc__.  To address issue 1. (but not 2. or 3.), you can implement house as a property with a setter. The idea is to update the aliases whenever the house attribute changes. This is not a good idea in general, but here is an alternative implementation to what you have in the question that will likely work a bit better: class House: def cleanup(self, arg1, arg2, kwarg1=False): """clean house is nice to live in!""" pass class Person: def __init__(self, house: House): self.house = house # use the property here @property def house(self): return self._house @house.setter def house(self, value): self._house = house self.cleanup_house = self._house.cleanup