5

Ok, this question has probably been answered somewhere but my Google-fu hasn't found the right combination of keywords yet.

I have a function that accepts a string, but when I pass None, Pycharm's inspection is flagging a type error. Is this an error in the linter? Does None count as a string? I know I can call the function with an empty string, but I think I should be able to use None as well.

def my_func(some_str):
""" does something
Arguments:
some_str (str): a string
"""
    # do something

...

my_func(None)  <-- throws Expected type 'str', got 'None' instead
jon_two
  • 1,073
  • 1
  • 23
  • 34
  • 1
    just pass empty string (`""`) instead of None – Stack Aug 09 '17 at 15:14
  • 1
    No because when performing an action on a string, it is only able to perform that operation on something which is of the type `str` however the value of `None` is a `NoneType`, which is its own individual type, meaning that `None` can not be used in place of a `str`, however you could use empty quotes, `""` which would pass in a string with no content – Professor_Joykill Aug 09 '17 at 15:17
  • 1
    `None` is not a string. `None` is `None`, a string is a `str`. PyCharm itself won't "throw" anything, neither will Python itself. Only some type check in the function itself might raise an actual error. So I'm unclear what you're asking… if the function rejects `None` as a valid argument, then the question is answering itself, no? – deceze Aug 09 '17 at 15:18
  • this seems like odd behaviour from pycharm to me. because python isn't strongly typed there is never any reason you can't pass a different type to the function, the function should handle appropriately. – Stael Aug 09 '17 at 15:19

3 Answers3

4

First to answer your question None is not a str It is the sole value of type.Nonetype it is a python Built in Contstant. Read about it here. And there are many ways to get around/handle possible None input

1. To get around it, not going to handle None:

is expecting str so of course, it throws an error. just pass in "" instead. but in this case calling my_func(None) would still give you an error.

my_func("") 

2. To Handle possible None input:

if you want to handle None as one of possible input parameter then set your parameter to optional parameter with * that way you can input None and not get an error

def my_func(*some_str):

OR

Default your input to None if the value user pass in is not None then you know user pass in something else: This allows you do to my_func(None) and not get an error

def my_func(some_str = None):
  if some_str:
    #do something

Note: this also allows you treat None and '' equally (thanks to Stael for pointing out)

OLIVER.KOO
  • 5,654
  • 3
  • 30
  • 62
  • if you do `if some_str:` then it will treat `None` and `''` equally, which is closer to what the OP is talking about. – Stael Aug 09 '17 at 15:33
1

None does not count as a string. None is the sole member of the class NoneType.

To do what you want, arrange for your function to accept an optional string argument.

def my_func(some_str: str = None):

Then don't pass it None, pass it nothing:

a = my_func()
BoarGules
  • 16,440
  • 2
  • 27
  • 44
  • In the actual code, there are more positional args after the str arg, so turning it into a kwarg is not an option, unfortunately. I don't want to make changes to the interface if I can avoid it. – jon_two Aug 10 '17 at 07:27
  • Mmm, that wasn't clear from your question. In that case I would simply forget about the type hint. – BoarGules Aug 10 '17 at 10:09
  • Sorry, guess I simplified it too much :-) – jon_two Aug 10 '17 at 13:44
  • 2
    If you really have to have the type hint because it's an inflexible project standard or something, then do: `from typing import Union` followed by `def my_func(some_str: Union[str,None]):` That expresses what you want and will shut PyCharm's linter up. – BoarGules Aug 11 '17 at 12:04
1

As a dissenting opinion, Python is not strongly typed so for pycharm's linter to highlight that as an error seems a little odd to me.

Of course there are many functions which legitimately need a string, but I'm sure i saw somewhere that 'good practice' for that was a function that looked more like this:

def myfunct(s):
    try:
        s = str(s)
    except TypeError:
        raise TypeError('message explaining function usage')
    # actual function

This works with anything that can be coerced into a string, which seems more sensible than requiring literally a string.

Am I nuts?

Stael
  • 2,619
  • 15
  • 19
  • I think the reason PyCharm is complaining about it, is because of the docstring that the code contains. I haven't used docstrings in Pycharm, so I don't know for sure, but that's the only reason I can think of. – SH7890 Aug 09 '17 at 17:25
  • I like this as it follows python's ask for forgiveness model. Also glad to see there are differences of opinion - it's not a straightforward question. – jon_two Aug 10 '17 at 07:40