一首诗 a écrit :
2 class, B contains C.

Given your code snippet, I assume you meant that B instances have an instance of C as attribute.

 When user want to use some service of C,

s/C/instances of C/


Python's classes are objects by themselves, so it's really important to make clear whether you're talking about the class object or instances of the class.

there are two choice:

First, more encapsulation:

=============================
class B:
    def newMethod(self):
        self.c.newMethod()

Don't expose 'c' as part of the API if you're after "more encapsulation". Reminder : by convention (and it's a really strong convention), attribute names starting with an underscore are implementation ('private' if you want to stick to mainstream jargon).

class C:
    def newMethod(self):

      #do something
        pass

b.newMethod()


yeps, composition/delegation. Classic scheme.

Sencond : Call seice of f c directly:
(snip)
b.c.newMethod()



Generally, what I learned from books told me that 1st choice is
better.

I _usually_ is, unless it's B's responsability to provide access to a C instance. But then, it's usually written as:

b = B()
c = b.get_c()
c.some_method()

This scheme is usually found when there's a need to connect to an external resource. A canonical example can be found the DB API, where you first open a connection to the database, then ask the connection for one (or more) cursor(s).

But when C has many many methods to expose to outer user, 2nd choice
seems to be more reasonable

Until you need to modify your implementation, or to have some code around the calls to methods of c, etc... The (potential) problem with the second scheme is that it may expose a bit too much of the implementation.

Hopefully, this may not be _that_ tragic with Python, since you can easily replace a direct attribute access with a computed one without impacting the client code - but not without paying some overhead (which FWIW you would have from the start using proper delegation).

I In the first design, B.newMethod did
nothing really useful.

Nope, or at least not directly. But then, why use the obj.method() syntax when C.method(c) would work too ?-)

More seriously: in lower-level, more static languages where you don't have the hand on attribute lookup, getting "proper encapsulation" right from the start is _really_ important. Python is more forgiving here since you have ways to customize attribute resolution. *But* it doesn't mean you should not pay attention to proper encapsulation.

ctaully, , there are D/E/F, etc. in B we methodhod has to be exposed
to user code,  which makes encapsulation more tedious.

In most languages, yeps. Good news, Python exposes enough of it's implementation to allow easy automation of the delegation. Read about the __getattr__ magic method.

Also and FWIW, writing dummy getters and setters for a dozen attributes is just as boring, and that's still the commonly accepted "best practice" in Java, C++ and most other mainstream "OO" languages.


In fact, these classes,  C/D/E/F all have different jobs, but they all
belongs to a real world object "B", B is only a container of C/D/E/F.

What is a "real world" object ?

And if B is only here to provide (almost direct) access to instances of C/D/E/F, do you really need B ? (open question - you may actually need this level of indirection for pretty good and legitimate reasons... but one can't tell without knowing way more about your concrete use case)

What do you think about it?

There are GoldenRules(tm) and BestPractices(tm). And then there's concrete application of all these things, and that's where the fun begin.

Blindly applying GoldenRules and BestPractices would border on cargo cult thinking. The real point behind GoldenRules etc is to draw your attention to known problems and the possible drawbacks of some conception/implementation choices, so you can make use of your own *informed* judgement wrt/ the concrete problem you're trying to solve.

IOW : there's no silver bullet, just a set of sound advices based on experience. Then it's up to you to decide which solution you think is the more appropriate here and now.
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to