Question: For example, if I'm reading some code that works like this:

```
list_of_objects = function_returning_object_list()
for object in list_of_objects:
    do_something(object.param)

```

isn't `object.get_param` kind of strange to see if you're just reading the code and don't know that `function_returning_object_list()` actually does return a list of objects? Without variable typing how do you avoid this kind of confusion through naming conventions?

Hope I'm clear.

Answer: 
This might be mostly an opinion based question but I'll attempt an answer.

Good variable names always help no matter the language. If you have a function with a name, say, `get_data`, you cannot really deduce that if that data is a single object or a list or what. But instead if you have a `class Bunny` and some function with the name `get_bunnies`, it is safe to assume that it will return some kind of collection. Of course there is always the question that whether the collection is a `list` or a `dict` for example. 

But if you are just reading the code like that, you can quickly deduce that if it is used with keywords, it is a `dict`, or some derivative of it.

The purpose of [Duck Typing](https://en.wikipedia.org/wiki/Duck_typing) is in short that "if it walks like a duck, swims like a duck and quacks like a duck, then it probably is a duck". Meaning that even if the `get_bunnies` returns some fancy subclass of `dict`, you should be able to use it like it is actually a `dict`, as long as it implements the right `__dunder__`-methods.

Duck typing always of course brings up some problems that strong typing does not, but that is usually just a matter of convention. If you are unsure that what some function will return, you can always test it: in your code, in the interpreter or even looking up the source.

About the "hungarian notation" of naming variables like `strName` or `name_string`... I have always agreed with Robert C. Martin that it brings unneeded redundancy to variable names. Of course the reduncancy is not that bad with dynamic typing, but even so, I dislike it. It tends to just make things harder when reading the code and searching through it. Or even more so, when the variable type is changed without changing the name...

If you have neither example code available nor good naming, you will need to either look up the source code, or hope that there is a docstring included in the function definition. If you are in luck and docstrings are defined *and up to date*, a good IDE will help you a lot to parse that string for you, or even the whole definition of the function, without the need to find the source file yourself.
Well, everything in Python IS indeed an object. Appropriate question here would be if each returned object has `param` attribute.

```
In [17]: a = 1

In [18]: type(a)
Out[18]: int

In [19]: b = 'b'

In [20]: type(b)
Out[20]: str

In [21]: c = True

In [22]: type(c)
Out[22]: bool

```

If You look at the examples above, You'll see that they're objects of type `str`, `int` and `bool`. Problem is that none of those have `param` attribute.