max
will just compare the elements in the list normally — i.e.
>>> 'b' > 300
True
The reason for why this is true is in the Python documentation, and is also discussed in detail in this answer: How does Python compare string and int.
Notably, from the documentation,
Objects of different types, except different numeric types and different string types, never compare equal; such objects are ordered consistently but arbitrarily
in other words, when you try to compare non-numeric, non-string types, implementations are free to order them however they choose, as long as it's consistent. For CPython, which is almost definitely what is relevant to you:
Objects of different types except numbers are ordered by their type names; objects of the same types that don’t support proper comparison are ordered by their address.
This behaviour can be demonstrated by making your own classes, e.g.
>>> class a(object):
... pass
...
>>> class z(object):
... pass
...
>>> class ZZZ(object):
... pass
...
>>> A = a()
>>> Z = z()
>>> foo = ZZZ() # It's the *type* name that matters, not the variable name.
>>> type(A)
<class '__main__.a'>
>>> type(Z)
<class '__main__.z'>
>>> type(foo)
<class '__main__.ZZZ'>
>>> A > 'a'
False
>>> Z > 'a'
True
>>> max(A, foo, Z)
<class '__main__.ZZZ'>